< Summary

Line coverage
37%
Covered lines: 3925
Uncovered lines: 6660
Coverable lines: 10585
Total lines: 15049
Line coverage: 37%
Branch coverage
34%
Covered branches: 2385
Total branches: 6918
Branch coverage: 34.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_AllowedToDependOnAllocationState()0%60%
File 1: get_Kind()0%40%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%1100%
File 1: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 1: .ctor(...)100%1100%
File 1: GetContext(...)100%1100%
File 1: VisitOneStatement(...)25%1230%
File 1: VisitTopLevelFrameExpression(...)100%10%
File 1: DesugarFunctionsInFrameClause(...)100%10%
File 1: FrameArrowToObjectSet(...)0%100%
File 1: VisitExpression(...)100%2100%
File 1: VisitOneExpression(...)8.33%368.88%
File 1: DiscoverBestBounds_MultipleVars(...)0%40%
File 1: DiscoverBestBounds_MultipleVars_AllowReordering(...)0%260%
File 1: DiscoverAllBounds_Aux_MultipleVars(...)0%40%
File 1: DiscoverAllBounds_SingleVar(...)100%10%
File 1: DiscoverAllBounds_Aux_SingleVar(...)0%1020%
File 1: DiscoverBoundsFunctionCallExpr(...)0%40%
File 1: NormalizedConjuncts()0%860%
File 1: SanitizeForBoundDiscovery(...)0%540%
File 1: IsMonotonic(...)0%120%
File 2: ResolveNamesAndInferTypes(...)100%4100%
File 2: ResolveNamesAndInferTypesForOneDeclarationInitial(...)62.5%857.57%
File 2: ResolveNamesAndInferTypesForOneDeclaration(...)50%1836.95%
File 2: EagerAddAssignableConstraint(...)100%4100%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: PrintTypeConstraintState(...)12.5%1623.52%
File 2: SolveAllTypeConstraints()20%1043.47%
File 2: ResolveAttributes(...)91.66%1283.33%
File 2: ResolveExpression(...)43.18%30845.51%
File 2: ResolveTypeParameters(...)80%1082.35%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainTypeExprBool(...)100%1100%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainAssignable(...)78.57%1490.47%
File 2: ConstrainAssignableTypeArgs(...)85.71%1478.37%
File 2: ConstrainSubtypeRelation_Equal(...)87.5%1677.77%
File 2: ConstrainSubtypeRelation(...)100%12100%
File 2: ConstrainSubtypeRelation_Aux(...)91.66%1291.66%
File 2: DetermineRootLeaf(...)87.03%5481.25%
File 2: .ctor(...)100%1100%
File 2: AssignProxyAndHandleItsConstraints(...)50%277.77%
File 2: AssignProxyAndHandleItsConstraints_aux(...)60.86%4653.12%
File 2: ImposeSubtypingConstraint(...)80%2086.66%
File 2: ConstrainTypeHead_Recursive(...)66.66%685.71%
File 2: ConstrainTypeHead(...)51.89%7963.23%
File 2: KeepConstraints(...)88.88%2783.33%
File 2: .ctor(...)100%1100%
File 2: ToString()0%40%
File 2: Confirm(...)61.52%51259.72%
File 2: ProxyWithNoSubTypeConstraint(...)70%1075%
File 2: CouldBeAnything()100%10%
File 2: FindCollectionType(...)72.22%1880.95%
File 2: .ctor(...)100%1100%
File 2: .ctor(...)100%1100%
File 2: PartiallySolveTypeConstraints(...)51.68%17850%
File 2: NewIntegerBasedProxy(...)100%1100%
File 2: ContainsAsTypeParameter(...)0%140%
File 2: AddAllProxies(...)100%4100%
File 2: ProcessAssignable(...)70.83%2459.37%
File 2: ConvertAssignableToSubtypeConstraints(...)100%14100%
File 2: TightenUpEquatable(...)90%10100%
File 2: ProcessOneSubtypingConstraintAndItsSubs(...)90%2096.15%
File 2: ProcessFullStrength_SubDirection(...)90%10100%
File 2: ProcessFullStrength_SuperDirection(...)100%10100%
File 2: AssignKnownEnd(...)46.42%2853.84%
File 2: AssignKnownEndsFullstrength(...)0%300%
File 2: AssignKnownEndsFullstrength_SubDirection(...)53.84%2665.78%
File 2: CloseOverAssignableRhss(...)0%140%
File 2: HasApplicableNullableRefTypeConstraint(...)0%60%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection(...)100%6100%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection_aux(...)20%1046.15%
File 2: AssignKnownEndsFullstrength_SuperDirection(...)93.33%3094.87%
File 2: Reaches(...)50%277.77%
File 2: Reaches_aux(...)72.22%1887.5%
File 2: ResolveClassMemberBodiesInitial(...)33.33%1242.1%
File 2: ResolveClassMemberBodies(...)63.63%2269.04%
File 2: ResolveCtorTypes(...)0%120%
File 2: ResolveCtorSignature(...)0%20%
File 2: AddDatatypeDependencyEdge(...)0%60%
File 2: ResolveFrameExpressionTopLevel(...)100%10%
File 2: ResolveFrameExpression(...)0%140%
File 2: ResolveIterator(...)0%240%
File 2: CheckIsLvalue(...)7.69%2619.35%
File 2: ResolveBlockStatement(...)37.5%847.05%
File 2: ResolveStatementWithLabels(...)12.5%825%
File 2: ResolveAlternatives(...)0%140%
File 2: ResolveCallStmt(...)50%3663.33%
File 2: ResolveActualParameters(...)40.32%6257.26%
File 2: GetLocationInformation(...)83.33%6100%
File 2: ResolveDotSuffix_Type(...)0%260%
File 2: CreateResolver_IdentifierExpr(...)75%1677.77%
File 2: ResolveStatement(...)17.73%28219.79%
File 2: ResolveLoopSpecificationComponents(...)0%120%
File 2: ResolveParameterDefaultValues(...)44.44%1841.66%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: .ctor(...)100%10%
File 2: ResolveTypeLenient(...)53.94%7647.74%
File 2: FillInTypeArguments(...)0%160%
File 2: TypeConstraintsIncludeProxy(...)100%1100%
File 2: TypeConstraintsIncludeProxy_Aux(...)22.22%1844%
File 2: ResolveTypeRhs(...)0%680%
File 2: ResolveMember(...)37.5%2436.95%
File 2: PartiallyResolveTypeForMemberSelection(...)52.04%9847.85%
File 2: GetBaseTypeFromProxy(...)100%1895.45%
File 2: GetBaseTypeFromProxy_Eq(...)100%2100%
File 2: GetBaseTypeFromProxy_EqAux(...)31.25%1639.13%
File 2: GetRelatedTypeProxies(...)81.25%3272%
File 2: JoinOfAllSubtypes(...)52.77%3670.27%
File 2: MeetOfAllSupertypes(...)96.87%3295.55%
File 2: CheckVariance(...)42.1%3854.9%
File 2: ConstrainToIntegerType(...)100%2100%
File 2: ResolveDatatypeUpdate(...)0%220%
File 2: DesugarDatatypeUpdate(...)0%160%
File 2: ResolveNameSegment(...)100%1100%
File 2: ResolveNameSegment(...)15.62%6426.8%
File 2: ResolveDatatypeConstructor(...)0%140%
File 2: ResolveNameSegment_Type(...)71.42%1477.41%
File 2: ResolveDotSuffix(...)20.73%8229.6%
File 2: CheckForAmbiguityInShadowedImportedModule(...)50%433.33%
File 2: NameConflictsWithModuleContents(...)0%100%
File 2: ResolveExprDotCall(...)58.33%4861.76%
File 2: ResolveApplySuffix(...)59.67%6268.31%
File 2: ResolveDatatypeValue(...)43.75%1670%
File 2: ResolveFunctionCallExpr(...)0%300%
File 2: ResolveReceiver(...)0%40%
File 2: ResolveSeqSelectExpr(...)87.5%896.77%
File 3: get_Options()100%1100%
File 3: .ctor(...)100%176.92%
File 3: get_Reporter()100%1100%
File 3: get_TypeConstraintErrorsToBeReported()100%1100%
File 3: RevealedInScope(...)0%20%
File 3: VisibleInScope(...)100%2100%
File 3: FreshTempVarName(...)0%20%
File 3: Create(...)0%100%
File 3: Name(...)0%40%
File 3: ModuleNames(...)0%40%
File 3: Create(...)0%20%
File 3: Equals(...)0%40%
File 3: GetHashCode(...)0%20%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: Create(...)0%20%
File 3: Equals(...)100%10%
File 3: GetHashCode(...)100%10%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: .ctor(...)100%4100%
File 3: AddRotateMember(...)100%1100%
File 3: ObjectInvariant()100%10%
File 3: AsValuetypeDecl(...)0%40%
File 3: CheckDupModuleNames(...)62.5%876.47%
File 3: ResolveProgram(...)72.29%14878.54%
File 3: ResolveValuetypeDecls()87.5%878.57%
File 3: ResolveModuleDefinition(...)29.16%2456.25%
File 3: ResolveModuleExport(...)10.89%15614.54%
File 3: CheckModuleExportConsistency(...)3.57%2810%
File 3: .ctor(...)100%1100%
File 3: BindName(...)50%287.5%
File 3: TryLookup(...)100%10%
File 3: TryLookupFilter(...)0%60%
File 3: get_ModuleList()100%10%
File 3: SubBindings(...)100%10%
File 3: BindModuleNames(...)28.12%3224.56%
File 3: ShortenPrefix(...)100%10%
File 3: BindModuleName_LiteralModuleDecl(...)0%80%
File 3: ResolveQualifiedModuleIdRootRefines(...)100%10%
File 3: ResolveQualifiedModuleIdRootImport(...)0%60%
File 3: ResolveQualifiedModuleIdRootAbstract(...)0%60%
File 3: ProcessDependenciesDefinition(...)20%2024.13%
File 3: ProcessDependencies(...)20%1030%
File 3: ModuleNotFoundErrorMessage(...)0%20%
File 3: EquivIfPresent(...)50%280%
File 3: MergeSignature(...)55%2057.14%
File 3: ResolveOpenedImports(...)50%1644.44%
File 3: ResolveAlias(...)0%20%
File 3: ResolveOpenedImportsWorker(...)0%360%
File 3: RegisterTopLevelDecls(...)68.88%9074.68%
File 3: RegisterMembers(...)26.47%3414.49%
File 3: RegisterByMethod(...)0%40%
File 3: MakeAbstractSignature(...)0%100%
File 3: CloneDeclaration(...)0%20%
File 3: ResolveModuleQualifiedId(...)0%120%
File 3: ResolveExport(...)0%180%
File 3: RevealAllInScope(...)100%12100%
File 3: ResolveTopLevelDecls_Signatures(...)55.76%5257.14%
File 3: .cctor()100%10%
File 3: ResolveTopLevelDecls_Core(...)45.93%39445.54%
File 3: FillInPostConditionsAndBodiesOfPrefixLemmas(...)2.94%342.5%
File 3: CheckIsOkayWithoutRHS(...)0%120%
File 3: ResolveClassMembers_Pass1(...)71.87%3271.42%
File 3: CheckForUnnecessaryEqualitySupportDeclarations(...)25%437.5%
File 3: CheckParameterDefaultValuesAreCompilable(...)12.5%837.5%
File 3: ReportCallGraphCycleError(...)100%10%
File 3: ReportCycleError(...)100%10%
File 3: MaxBV(...)100%10%
File 3: MaxBV(...)100%10%
File 3: FigureOutNativeType(...)0%4670%
File 3: CheckOlderParameters(...)90%1077.77%
File 3: CheckExpression(...)100%1100%
File 3: CheckExpression(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneExpr(...)50%853.84%
File 3: VisitOneStmt(...)41.66%1245.45%
File 3: CheckForFuelAdjustments(...)3.57%2814.81%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)100%1100%
File 3: Invert(...)0%40%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%520%
File 3: KNatMismatchError(...)0%60%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%180%
File 3: VisitOneStmt(...)0%40%
File 3: ExtremePredicateChecks(...)100%10%
File 3: .ctor(...)100%10%
File 3: VisitOneStmt(...)0%80%
File 3: VisitOneExpr(...)0%40%
File 3: ExtremeLemmaChecks(...)100%10%
File 3: ExtremeLemmaChecks(...)0%20%
File 3: CheckTypeCharacteristics_Stmt(...)100%1100%
File 3: CheckTypeCharacteristics_Expr(...)100%1100%
File 3: CheckTypeCharacteristics_Type(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)42.85%5635.55%
File 3: VisitOneExpr(...)70.27%7469.41%
File 3: VisitType(...)46.66%3066.66%
File 3: CheckTypeInstantiation(...)50%672.72%
File 3: CheckCharacteristics(...)46.66%3042.3%
File 3: TypeEqualityErrorMessageHint(...)0%60%
File 3: CanCompareWith(...)6.25%1620%
File 3: ComputeGhostInterest(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)50%444.44%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)10%1015%
File 3: .ctor(...)100%1100%
File 3: CheckInit(...)100%10%
File 3: CheckInit(...)0%80%
File 3: VisitExpr(...)100%10%
File 3: VisitOneExpr(...)0%100%
File 3: LiberalRHSVisit(...)0%240%
File 3: IsThisDotField(...)0%20%
File 3: IsCollectionOperator(...)0%100%
File 3: InferRequiredEqualitySupport(...)43.75%3266.66%
File 3: ResolveParentTraitTypes(...)4.54%2229.62%
File 3: RegisterInheritedMembers(...)12.5%4815.94%
File 3: ResolveClassMemberTypes(...)50%2450.98%
File 3: InheritedTraitMembers(...)7.89%7610%
File 3: CheckOverride_FunctionParameters(...)0%120%
File 3: CheckOverride_MethodParameters(...)0%100%
File 3: CheckOverride_TypeParameters(...)0%160%
File 3: CheckOverride_ResolvedParameters(...)0%300%
File 3: SccStratosphereCheck(...)0%140%
File 3: ComputeGroundingCtor(...)0%180%
File 3: CheckCanBeConstructed(...)0%360%
File 3: DetermineEqualitySupport(...)0%620%
File 3: IsRecognizedAttribute(...)0%500%
File 3: ScopePushAndReport(...)100%1100%
File 3: ScopePushAndReport(...)50%455.55%
File 3: ResolveFunctionSignature(...)75%877.77%
File 3: DisallowNonGhostFieldSpecifiers(...)0%40%
File 3: ResolveMethodSignature(...)75%887.5%
File 3: ResolveIteratorSignature(...)0%160%
File 3: ObjectInvariant()100%10%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: ResolvedArrayType(...)100%10%
File 3: FillInDefaultLoopDecreases(...)0%1070%
File 3: VarDotMethod(...)100%10%
File 3: makeTemp(...)100%10%
File 3: EnsureSupportsErrorHandling(...)0%200%
File 3: CheckLocalityUpdates(...)0%260%
File 3: CheckLocalityUpdatesLhs(...)0%40%
File 3: .ctor(...)100%10%
File 3: ToString()0%20%
File 3: FindAllMembers(...)0%20%
File 3: GetThisType(...)50%466.66%
File 3: GetReceiverType(...)100%10%
File 3: ResolveDominatingLabelInExpr(...)0%60%
File 3: VarDotFunction(...)100%10%
File 3: LetPatIn(...)100%10%
File 3: LetVarIn(...)100%10%
File 3: ResolveLetOrFailExpr(...)0%20%
File 3: SelectAppropriateArrowTypeForFunction(...)100%1100%
File 3: SelectAppropriateArrowType(...)50%480%
File 3: ConstrainToIntegerType(...)100%1100%
File 3: ResolveNestedMatchExpr(...)100%10%
File 3: ResolveCasePattern(...)22%5026.58%
File 3: FillInDefaultValueExpressions()50%271.42%
File 3: FillInDefaultValueExpression(...)0%40%
File 3: .ctor(...)100%10%
File 3: Substitute(...)0%20%
File 3: BuildTypeArgumentSubstitute(...)62.5%873.33%
File 3: AddParentTypeParameterSubstitutions(...)60%1075%
File 3: GhostPrefix(...)50%2100%
File 3: GetSignatureExt(...)0%40%
File 3: GetSignature(...)100%10%
File 3: GetImpliedTypeConstraint(...)100%1100%
File 3: GetImpliedTypeConstraint(...)50%860%
File 3: FreeVariables(...)0%340%
File 3: .cctor()100%1100%
File 3: get_Msg()0%80%
File 3: .ctor(...)100%1100%
File 3: ResolveOp(...)80%10582.78%
File 3: CollectFriendlyCallsInExtremeLemmaSpecification(...)0%20%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%280%
File 4: get_IsPrefixPredicate()100%1100%
File 4: get_IsExtremePredicate()100%1100%
File 4: get_IsPrefixDeclaration()50%2100%
File 4: .ctor(...)100%1100%
File 4: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 4: get_reporter()100%10%
File 4: .ctor(...)100%1100%
File 4: GetContext(...)100%1100%
File 4: VisitOneDeclaration(...)25%2023.33%
File 4: VisitField(...)50%257.14%
File 4: VisitOneStatement(...)50%244.44%
File 4: PostVisitOneStatement(...)58.33%1252.17%
File 4: PostVisitOneExpression(...)47.97%17346.69%
File 4: VisitExtendedPattern(...)0%40%
File 4: IsDetermined(...)100%2100%
File 4: CheckTypeIsDetermined(...)25%445.45%
File 4: CheckTypeArgsContainNoOrdinal(...)50%2100%
File 4: CheckContainsNoOrdinal(...)50%271.42%

File(s)

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/BoundsDiscovery.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright by the contributors to the Dafny Project
 4// SPDX-License-Identifier: MIT
 5//
 6//-----------------------------------------------------------------------------
 7using System.Collections.Generic;
 8using System.Linq;
 9using System.Diagnostics.Contracts;
 10using Microsoft.Boogie;
 11
 12namespace Microsoft.Dafny {
 13  public partial class Resolver {
 14    private class BoundsDiscoveryVisitor : ASTVisitor<BoundsDiscoveryVisitor.BoundsDiscoveryContext> {
 15      public class BoundsDiscoveryContext : IASTVisitorContext {
 16        private readonly IASTVisitorContext astVisitorContext;
 17        readonly bool inLambdaExpression;
 18
 19        public bool AllowedToDependOnAllocationState =>
 020          !(astVisitorContext is Function or ConstantField or RedirectingTypeDecl || inLambdaExpression);
 21
 22        public string Kind {
 023          get {
 24            // assumes context denotes a lambda expression, redirecting type, or member declaration
 025            if (inLambdaExpression) {
 026              return "lambda expression";
 27            }
 28            string kind;
 029            if (astVisitorContext is RedirectingTypeDecl redirectingTypeDecl) {
 030              kind = redirectingTypeDecl.WhatKind;
 031            } else {
 032              var memberDecl = (MemberDecl)astVisitorContext;
 033              kind = memberDecl.WhatKind;
 034            }
 035            return $"{kind} definition";
 036          }
 37        }
 38
 4009039        public BoundsDiscoveryContext(IASTVisitorContext astVisitorContext) {
 2004540          this.astVisitorContext = astVisitorContext;
 2004541          this.inLambdaExpression = false;
 2004542        }
 43
 44        /// <summary>
 45        /// This constructor is used to say that, within parentContext, the context is inside a lambda
 46        /// expression.
 47        /// </summary>
 1072048        public BoundsDiscoveryContext(BoundsDiscoveryContext parentContext, LambdaExpr lambdaExpr) {
 536049          this.astVisitorContext = parentContext.astVisitorContext;
 536050          this.inLambdaExpression = true;
 536051        }
 52
 844053        ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 54      }
 55
 56      private readonly ErrorReporter reporter;
 57
 249058      public BoundsDiscoveryVisitor(ErrorReporter reporter) {
 124559        this.reporter = reporter;
 124560      }
 61
 2004562      public override BoundsDiscoveryContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostconditi
 2004563        return new BoundsDiscoveryContext(astVisitorContext);
 2004564      }
 65
 119880066      protected override bool VisitOneStatement(Statement stmt, BoundsDiscoveryContext context) {
 119880067        if (stmt is ForallStmt forallStmt) {
 068          forallStmt.Bounds = DiscoverBestBounds_MultipleVars(forallStmt.BoundVars, forallStmt.Range, true);
 069          if (forallStmt.Body == null) {
 070            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, forallStmt.Tok, "note, this forall statement 
 071          }
 119880072        } else if (stmt is AssignSuchThatStmt assignSuchThatStmt) {
 073          if (assignSuchThatStmt.AssumeToken == null) {
 074            var varLhss = new List<IVariable>();
 075            foreach (var lhs in assignSuchThatStmt.Lhss) {
 076              var ide = (IdentifierExpr)lhs.Resolved;  // successful resolution implies all LHS's are IdentifierExpr's
 077              varLhss.Add(ide.Var);
 078            }
 079            assignSuchThatStmt.Bounds = DiscoverBestBounds_MultipleVars(varLhss, assignSuchThatStmt.Expr, true);
 080          }
 119880081        } else if (stmt is OneBodyLoopStmt oneBodyLoopStmt) {
 082          oneBodyLoopStmt.ComputeBodySurrogate(reporter);
 083        }
 84
 119880085        return base.VisitOneStatement(stmt, context);
 119880086      }
 87
 088      public override void VisitTopLevelFrameExpression(FrameExpression frameExpression, BoundsDiscoveryContext context)
 089        DesugarFunctionsInFrameClause(frameExpression);
 090        base.VisitTopLevelFrameExpression(frameExpression, context);
 091      }
 92
 093      void DesugarFunctionsInFrameClause(FrameExpression frameExpression) {
 094        frameExpression.DesugaredExpression = FrameArrowToObjectSet(frameExpression.E);
 095      }
 96
 97      /// <summary>
 98      /// The motivation for this method is to convert a reads-clause frame expression "f.reads" into a set.
 99      /// More generally, if the given expression "e" has type "X ~> collection<Y>", for some list of type X,
 100      /// some reference type Y, and "collection" being "set", "iset", "seq", or "multiset", then this method
 101      /// returns an expression of type "set<Y>" denoting
 102      ///
 103      ///     UNION x: X :: e(x)                      // e.g., UNION x: X :: f.reads(x)
 104      ///
 105      /// For example, if "e" is an expression "f.reads" of type "X ~> set<object>", then the expression
 106      /// returned is the union of "f.reads(x)" over all inputs "x" to "f".
 107      ///
 108      /// If the type of "e" is not of the form "X ~> collection<Y>" as stated above, then this method simply
 109      /// returns the given "e".
 110      ///
 111      /// Dafny does not have a UNION comprehension, so the expression returned has the form
 112      ///
 113      ///     { obj: Y | exists x: X :: obj in e(x) }
 114      ///
 115      /// which in Dafny notation is written
 116      ///
 117      ///     set x: X, obj: Y | obj in e(x) :: obj
 118      ///
 119      /// Note, since Y is a reference type and there is, at any one time, only a finite number of references,
 120      /// the result type is finite.
 121      ///
 122      /// Note: A pending improvement would be to limit the range of the set comprehension to the values for x
 123      /// that satisfy e's precondition.
 124      /// </summary>
 0125      public static Expression FrameArrowToObjectSet(Expression e) {
 126        Contract.Requires(e != null);
 0127        var arrowType = e.Type.AsArrowType;
 0128        if (arrowType == null) {
 0129          return e;
 130        }
 0131        var collectionType = arrowType.Result.AsCollectionType;
 0132        if (collectionType == null || collectionType.NormalizeExpand() is MapType) {
 0133          return e;
 134        }
 0135        var elementType = collectionType.Arg; // "elementType" is called "Y" in the description of this method, above
 0136        if (!elementType.IsRefType) {
 0137          return e;
 138        }
 139
 0140        var boundVarDecls = new List<BoundVar>();
 0141        var boundVarUses = new List<Expression>();
 0142        var i = 0;
 0143        foreach (var functionArgumentType in arrowType.Args) {
 0144          var bv = new BoundVar(e.tok, $"_x{i}", functionArgumentType);
 0145          boundVarDecls.Add(bv);
 0146          boundVarUses.Add(new IdentifierExpr(e.tok, bv.Name) { Type = bv.Type, Var = bv });
 0147          i++;
 0148        }
 0149        var objVar = new BoundVar(e.tok, "_obj", elementType);
 0150        var objUse = new IdentifierExpr(e.tok, objVar.Name) { Type = objVar.Type, Var = objVar };
 0151        boundVarDecls.Add(objVar);
 152
 0153        var collection = new ApplyExpr(e.tok, e, boundVarUses, e.tok) {
 0154          Type = collectionType
 0155        };
 0156        var resolvedOpcode = collectionType.ResolvedOpcodeForIn;
 157
 0158        var inCollection = new BinaryExpr(e.tok, BinaryExpr.Opcode.In, objUse, collection) {
 0159          ResolvedOp = resolvedOpcode,
 0160          Type = Type.Bool
 0161        };
 162
 0163        var attributes = new Attributes("_reads", new List<Expression>(), null);
 0164        return new SetComprehension(e.tok, e.RangeToken, true, boundVarDecls, inCollection, objUse, attributes) {
 0165          Type = new SetType(true, elementType)
 0166        };
 0167      }
 168
 2771515169      protected override void VisitExpression(Expression expr, BoundsDiscoveryContext context) {
 2776875170        if (expr is LambdaExpr lambdaExpr) {
 5360171          lambdaExpr.Reads.Iter(DesugarFunctionsInFrameClause);
 172
 173          // Make the context more specific when visiting inside a lambda expression
 5360174          context = new BoundsDiscoveryContext(context, lambdaExpr);
 5360175        }
 2771515176        base.VisitExpression(expr, context);
 2771515177      }
 178
 2771515179      protected override bool VisitOneExpression(Expression expr, BoundsDiscoveryContext context) {
 2771515180        if (expr is ComprehensionExpr and not LambdaExpr) {
 0181          var e = (ComprehensionExpr)expr;
 182          // apply bounds discovery to quantifiers, finite sets, and finite maps
 0183          Expression whereToLookForBounds = null;
 0184          var polarity = true;
 0185          if (e is QuantifierExpr quantifierExpr) {
 0186            whereToLookForBounds = quantifierExpr.LogicalBody();
 0187            polarity = quantifierExpr is ExistsExpr;
 0188          } else if (e is SetComprehension setComprehension) {
 0189            whereToLookForBounds = setComprehension.Range;
 0190          } else if (e is MapComprehension) {
 0191            whereToLookForBounds = e.Range;
 0192          } else {
 0193            Contract.Assert(false);  // otherwise, unexpected ComprehensionExpr
 0194          }
 0195          if (whereToLookForBounds != null) {
 0196            e.Bounds = DiscoverBestBounds_MultipleVars_AllowReordering(e.BoundVars, whereToLookForBounds, polarity);
 0197            if (2 <= reporter.Options.Allocated && !context.AllowedToDependOnAllocationState) {
 0198              foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds,
 0199                         ComprehensionExpr.BoundedPool.PoolVirtues.IndependentOfAlloc)) {
 0200                var how = Attributes.Contains(e.Attributes, "_reads") ? "(implicitly by using a function in a reads clau
 0201                var message =
 0202                  $"a {e.WhatKind} involved in a {context.Kind} {how}is not allowed to depend on the set of allocated re
 0203                  $" but values of '{bv.Name}' (of type '{bv.Type}') may contain references";
 0204                if (bv.Type.IsTypeParameter || bv.Type.IsAbstractType) {
 0205                  message += $" (perhaps declare its type as '{bv.Type}(!new)')";
 0206                }
 0207                message += " (see documentation for 'older' parameters)";
 0208                reporter.Error(MessageSource.Resolver, e, message);
 0209              }
 0210            }
 211
 0212            if ((e as SetComprehension)?.Finite == true || (e as MapComprehension)?.Finite == true) {
 213              // the comprehension had better produce a finite set
 0214              if (e.Type.HasFinitePossibleValues) {
 215                // This means the set is finite, regardless of if the Range is bounded.  So, we don't give any error her
 216                // However, if this expression is used in a non-ghost context (which is not yet known at this stage of
 217                // resolution), the resolver will generate an error about that later.
 0218              } else {
 219                // we cannot be sure that the set/map really is finite
 0220                foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds, ComprehensionExpr.
 0221                  reporter.Error(MessageSource.Resolver, e,
 0222                    "the result of a {0} must be finite, but Dafny's heuristics can't figure out how to produce a bounde
 0223                    e.WhatKind, bv.Name);
 0224                }
 0225              }
 0226            }
 0227          }
 228
 0229        }
 230
 2771515231        return base.VisitOneExpression(expr, context);
 2771515232      }
 233    }
 234
 235    /// <summary>
 236    /// For a list of variables "bvars", returns a list of best bounds for each respective variable.
 237    /// If no bound is found for a variable "v", then the bound for "v" in the returned list is set to "null".
 238    /// </summary>
 239    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars<VT>(List<VT> bvars, Expression exp
 0240      bool polarity) where VT : IVariable {
 241      Contract.Requires(bvars != null);
 242      Contract.Requires(expr != null);
 243      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0244      foreach (var bv in bvars) {
 0245        var c = GetImpliedTypeConstraint(bv, bv.Type);
 0246        expr = polarity ? Expression.CreateAnd(c, expr) : Expression.CreateImplies(c, expr);
 0247      }
 0248      var bests = DiscoverAllBounds_Aux_MultipleVars(bvars, expr, polarity);
 0249      return bests;
 0250    }
 251
 252    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars_AllowReordering<VT>(List<VT> bvars
 0253      bool polarity) where VT : IVariable {
 254      Contract.Requires(bvars != null);
 255      Contract.Requires(expr != null);
 256      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0257      var bounds = DiscoverBestBounds_MultipleVars(bvars, expr, polarity);
 0258      if (bvars.Count > 1) {
 259        // It may be helpful to try all permutations (or, better yet, to use an algorithm that keeps track of the depend
 260        // and discovers good bounds more efficiently). However, all permutations would be expensive. Therefore, we try 
 261        // other permutation, namely the reversal "bvars". This covers the important case where there are two bound vari
 262        // that work out in the opposite order. It also covers one more case for the (probably rare) case of there being
 263        // than two bound variables.
 0264        var bvarsMissyElliott = new List<VT>(bvars);  // make a copy
 0265        bvarsMissyElliott.Reverse();  // and then flip it and reverse it, Ti esrever dna ti pilf nwod gnaht ym tup I
 0266        var boundsMissyElliott = DiscoverBestBounds_MultipleVars(bvarsMissyElliott, expr, polarity);
 267        // Figure out which one seems best
 0268        var meBetter = 0;
 0269        for (int i = 0; i < bvars.Count; i++) {
 0270          var orig = bounds[i];
 0271          var me = boundsMissyElliott[i];
 0272          if (orig == null && me != null) {
 0273            meBetter = 1; break; // end game
 0274          } else if (orig != null && me == null) {
 0275            meBetter = -1; break; // end game
 0276          } else if (orig != null && me != null) {
 0277            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter--; }
 0278            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter--; }
 0279            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter++; }
 0280            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter++; }
 0281          }
 0282        }
 0283        if (meBetter > 0) {
 284          // yes, this reordering seems to have been better
 0285          bvars.Reverse();
 0286          return boundsMissyElliott;
 287        }
 0288      }
 0289      return bounds;
 0290    }
 291
 292    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_MultipleVars<VT>(List<VT> bvars, Expression
 0293      bool polarity) where VT : IVariable {
 294      Contract.Requires(bvars != null);
 295      Contract.Requires(expr != null);
 296      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 297      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>().Count == bvars.Count);
 0298      var knownBounds = new List<ComprehensionExpr.BoundedPool>();
 0299      for (var j = 0; j < bvars.Count; j++) {
 0300        knownBounds.Add(null);
 0301      }
 302      // Note, in the following loop, it's important to go backwards, because DiscoverAllBounds_Aux_SingleVar assumes "k
 303      // filled in for higher-indexed variables.
 0304      for (var j = bvars.Count; 0 <= --j;) {
 0305        var bounds = DiscoverAllBounds_Aux_SingleVar(bvars, j, expr, polarity, knownBounds);
 0306        knownBounds[j] = ComprehensionExpr.BoundedPool.GetBest(bounds);
 307#if DEBUG_PRINT
 308        if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 309          var ib = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 310          var lo = ib.LowerBound == null ? "" : Printer.ExprToString(ib.LowerBound);
 311          var hi = ib.UpperBound == null ? "" : Printer.ExprToString(ib.UpperBound);
 312          Console.WriteLine("DEBUG: Bound for var {3}, {0}:  {1} .. {2}", bvars[j].Name, lo, hi, j);
 313        } else if (knownBounds[j] is ComprehensionExpr.SetBoundedPool) {
 314          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  in {1}", bvars[j].Name, Printer.ExprToString(((Comprehensio
 315        } else {
 316          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  {1}", bvars[j].Name, knownBounds[j], j);
 317        }
 318#endif
 0319      }
 0320      return knownBounds;
 0321    }
 322
 0323    public static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_SingleVar<VT>(VT v, Expression expr) where VT : 
 0324      expr = Expression.CreateAnd(GetImpliedTypeConstraint(v, v.Type), expr);
 0325      return DiscoverAllBounds_Aux_SingleVar(new List<VT> { v }, 0, expr, true, new List<ComprehensionExpr.BoundedPool>(
 0326    }
 327
 328    /// <summary>
 329    /// Returns a list of (possibly partial) bounds for "bvars[j]", each of which can be written without mentioning any 
 330    /// that is not bounded.
 331    /// </summary>
 332    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_SingleVar<VT>(List<VT> bvars, int j, Expres
 0333      bool polarity, List<ComprehensionExpr.BoundedPool> knownBounds) where VT : IVariable {
 334      Contract.Requires(bvars != null);
 335      Contract.Requires(0 <= j && j < bvars.Count);
 336      Contract.Requires(expr != null);
 337      Contract.Requires(knownBounds != null);
 338      Contract.Requires(knownBounds.Count == bvars.Count);
 0339      var bv = bvars[j];
 0340      var bounds = new List<ComprehensionExpr.BoundedPool>();
 341
 342      // Maybe the type itself gives a bound
 0343      if (bv.Type.IsBoolType) {
 0344        bounds.Add(new ComprehensionExpr.BoolBoundedPool());
 0345      } else if (bv.Type.IsCharType) {
 0346        bounds.Add(new ComprehensionExpr.CharBoundedPool());
 0347      } else if (bv.Type.IsDatatype && bv.Type.AsDatatype.HasFinitePossibleValues) {
 0348        bounds.Add(new ComprehensionExpr.DatatypeBoundedPool(bv.Type.AsDatatype));
 0349      } else if (bv.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0350        bounds.Add(new AssignSuchThatStmt.WiggleWaggleBound());
 0351      } else if (!bv.Type.MayInvolveReferences) {
 0352        bounds.Add(new ComprehensionExpr.AllocFreeBoundedPool(bv.Type));
 0353      }
 354
 355      // Go through the conjuncts of the range expression to look for bounds.
 0356      foreach (var conjunct in NormalizedConjuncts(expr, polarity)) {
 0357        if (conjunct is IdentifierExpr) {
 0358          var ide = (IdentifierExpr)conjunct;
 0359          if (ide.Var == (IVariable)bv) {
 0360            Contract.Assert(bv.Type.IsBoolType);
 0361            bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, true)));
 0362          }
 0363          continue;
 364        }
 0365        if (conjunct is UnaryOpExpr || conjunct is OldExpr) {
 366          // we also consider a unary expression sitting immediately inside an old
 0367          var unary = conjunct as UnaryOpExpr ?? ((OldExpr)conjunct).E.Resolved as UnaryOpExpr;
 0368          if (unary != null) {
 0369            var ide = unary.E.Resolved as IdentifierExpr;
 0370            if (ide != null && ide.Var == (IVariable)bv) {
 0371              if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot) {
 0372                bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, false)));
 0373              } else if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.Allocated) {
 0374                bounds.Add(new ComprehensionExpr.ExplicitAllocatedBoundedPool());
 0375              }
 0376            }
 0377          }
 0378          continue;
 379        }
 0380        if (conjunct is FunctionCallExpr functionCallExpr) {
 0381          DiscoverBoundsFunctionCallExpr(functionCallExpr, bv, bounds);
 0382          continue;
 383        }
 0384        var c = conjunct as BinaryExpr;
 0385        if (c == null) {
 386          // other than what we already covered above, we only know what to do with binary expressions
 0387          continue;
 388        }
 0389        var e0 = c.E0;
 0390        var e1 = c.E1;
 0391        int whereIsBv = SanitizeForBoundDiscovery(bvars, j, c.ResolvedOp, knownBounds, ref e0, ref e1);
 0392        if (whereIsBv < 0) {
 0393          continue;
 394        }
 0395        switch (c.ResolvedOp) {
 396          case BinaryExpr.ResolvedOpcode.InSet:
 0397            if (whereIsBv == 0) {
 0398              bounds.Add(new ComprehensionExpr.SetBoundedPool(e1, e0.Type, e1.Type.AsSetType.Arg, e1.Type.AsSetType.Fini
 0399            }
 0400            break;
 401          case BinaryExpr.ResolvedOpcode.Subset:
 0402            if (whereIsBv == 0) {
 0403              bounds.Add(new ComprehensionExpr.SubSetBoundedPool(e1, e1.Type.AsSetType.Finite));
 0404            } else {
 0405              bounds.Add(new ComprehensionExpr.SuperSetBoundedPool(e0));
 0406            }
 0407            break;
 408          case BinaryExpr.ResolvedOpcode.InMultiSet:
 0409            if (whereIsBv == 0) {
 0410              bounds.Add(new ComprehensionExpr.MultiSetBoundedPool(e1, e0.Type, e1.Type.AsMultiSetType.Arg));
 0411            }
 0412            break;
 413          case BinaryExpr.ResolvedOpcode.InSeq:
 0414            if (whereIsBv == 0 && e1.Type.AsSeqType is { } seqType) {
 0415              bounds.Add(new ComprehensionExpr.SeqBoundedPool(e1, e0.Type, seqType.Arg));
 0416            }
 0417            break;
 418          case BinaryExpr.ResolvedOpcode.InMap:
 0419            if (whereIsBv == 0) {
 0420              bounds.Add(new ComprehensionExpr.MapBoundedPool(e1, e0.Type, e1.Type.AsMapType.Arg, e1.Type.AsMapType.Fini
 0421            }
 0422            break;
 423          case BinaryExpr.ResolvedOpcode.EqCommon:
 424          case BinaryExpr.ResolvedOpcode.SetEq:
 425          case BinaryExpr.ResolvedOpcode.SeqEq:
 426          case BinaryExpr.ResolvedOpcode.MultiSetEq:
 427          case BinaryExpr.ResolvedOpcode.MapEq:
 0428            var otherOperand = whereIsBv == 0 ? e1 : e0;
 0429            bounds.Add(new ComprehensionExpr.ExactBoundedPool(otherOperand));
 0430            break;
 431          case BinaryExpr.ResolvedOpcode.Gt:
 432          case BinaryExpr.ResolvedOpcode.Ge:
 0433            Contract.Assert(false);
 0434            throw new cce.UnreachableException(); // promised by postconditions of NormalizedConjunct
 435          case BinaryExpr.ResolvedOpcode.Lt:
 0436            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0437              if (whereIsBv == 0) {
 438                // bv < E
 0439                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, e1));
 0440              } else {
 441                // E < bv
 0442                bounds.Add(new ComprehensionExpr.IntBoundedPool(Expression.CreateIncrement(e0, 1), null));
 0443              }
 0444            }
 0445            break;
 446          case BinaryExpr.ResolvedOpcode.Le:
 0447            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0448              if (whereIsBv == 0) {
 449                // bv <= E
 0450                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, Expression.CreateIncrement(e1, 1)));
 0451              } else {
 452                // E <= bv
 0453                bounds.Add(new ComprehensionExpr.IntBoundedPool(e0, null));
 0454              }
 0455            }
 0456            break;
 457          case BinaryExpr.ResolvedOpcode.RankLt:
 0458            if (whereIsBv == 0) {
 0459              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e0.Type.IsIndDatatype));
 0460            }
 0461            break;
 462          case BinaryExpr.ResolvedOpcode.RankGt:
 0463            if (whereIsBv == 1) {
 0464              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e1.Type.IsIndDatatype));
 0465            }
 0466            break;
 467          default:
 0468            break;
 469        }
 0470      }
 0471      return bounds;
 0472    }
 473
 474    private static void DiscoverBoundsFunctionCallExpr<VT>(FunctionCallExpr fce, VT boundVariable, List<ComprehensionExp
 0475      where VT : IVariable {
 476      Contract.Requires(fce != null);
 477      Contract.Requires(boundVariable != null);
 478      Contract.Requires(bounds != null);
 479
 0480      var formals = fce.Function.Formals;
 0481      Contract.Assert(formals.Count == fce.Args.Count);
 0482      if (LinqExtender.Zip(formals, fce.Args).Any(t => t.Item1.IsOlder && t.Item2.Resolved is IdentifierExpr ide && ide.
 0483        bounds.Add(new ComprehensionExpr.OlderBoundedPool());
 0484        return;
 485      }
 0486    }
 487
 488    /// <summary>
 489    /// Returns all conjuncts of "expr" in "polarity" positions.  That is, if "polarity" is "true", then
 490    /// returns the conjuncts of "expr" in positive positions; else, returns the conjuncts of "expr" in
 491    /// negative positions.  The method considers a canonical-like form of the expression that pushes
 492    /// negations inwards far enough that one can determine what the result is going to be (so, almost
 493    /// a negation normal form).
 494    /// As a convenience, arithmetic inequalities are rewritten so that the negation of an arithmetic
 495    /// inequality is never returned and the comparisons > and >= are never returned; the negation of
 496    /// a common equality or disequality is rewritten analogously.
 497    /// Requires "expr" to be successfully resolved.
 498    /// Ensures that what is returned is not a ConcreteSyntaxExpression.
 499    /// </summary>
 0500    static IEnumerable<Expression> NormalizedConjuncts(Expression expr, bool polarity) {
 501      // We consider 5 cases.  To describe them, define P(e)=Conjuncts(e,true) and N(e)=Conjuncts(e,false).
 502      //   *  X ==> Y    is treated as a shorthand for !X || Y, and so is described by the remaining cases
 503      //   *  X && Y     P(_) = P(X),P(Y)    and    N(_) = !(X && Y)
 504      //   *  X || Y     P(_) = (X || Y)     and    N(_) = N(X),N(Y)
 505      //   *  !X         P(_) = N(X)         and    N(_) = P(X)
 506      //   *  else       P(_) = else         and    N(_) = !else
 507      // So for ==>, we have:
 508      //   *  X ==> Y    P(_) = P(!X || Y) = (!X || Y) = (X ==> Y)
 509      //                 N(_) = N(!X || Y) = N(!X),N(Y) = P(X),N(Y)
 0510      expr = expr.Resolved;
 511
 512      // Binary expressions
 0513      var b = expr as BinaryExpr;
 0514      if (b != null) {
 0515        bool breakDownFurther = false;
 0516        bool p0 = polarity;
 0517        switch (b.ResolvedOp) {
 518          case BinaryExpr.ResolvedOpcode.And:
 0519            breakDownFurther = polarity;
 0520            break;
 521          case BinaryExpr.ResolvedOpcode.Or:
 0522            breakDownFurther = !polarity;
 0523            break;
 524          case BinaryExpr.ResolvedOpcode.Imp:
 0525            breakDownFurther = !polarity;
 0526            p0 = !p0;
 0527            break;
 528          default:
 0529            break;
 530        }
 0531        if (breakDownFurther) {
 0532          foreach (var c in NormalizedConjuncts(b.E0, p0)) {
 0533            yield return c;
 0534          }
 0535          foreach (var c in NormalizedConjuncts(b.E1, polarity)) {
 0536            yield return c;
 0537          }
 0538          yield break;
 539        }
 0540      }
 541
 542      // Unary expression
 0543      var u = expr as UnaryOpExpr;
 0544      if (u != null && u.Op == UnaryOpExpr.Opcode.Not) {
 0545        foreach (var c in NormalizedConjuncts(u.E, !polarity)) {
 0546          yield return c;
 0547        }
 0548        yield break;
 549      }
 550
 551      // no other case applied, so return the expression or its negation, but first clean it up a little
 0552      b = expr as BinaryExpr;
 0553      if (b != null) {
 554        BinaryExpr.Opcode newOp;
 555        BinaryExpr.ResolvedOpcode newROp;
 556        bool swapOperands;
 0557        switch (b.ResolvedOp) {
 558          case BinaryExpr.ResolvedOpcode.Gt:  // A > B         yield polarity ? (B < A) : (A <= B);
 0559            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0560            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0561            swapOperands = polarity;
 0562            break;
 563          case BinaryExpr.ResolvedOpcode.Ge:  // A >= B        yield polarity ? (B <= A) : (A < B);
 0564            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0565            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0566            swapOperands = polarity;
 0567            break;
 568          case BinaryExpr.ResolvedOpcode.Le:  // A <= B        yield polarity ? (A <= B) : (B < A);
 0569            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0570            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0571            swapOperands = !polarity;
 0572            break;
 573          case BinaryExpr.ResolvedOpcode.Lt:  // A < B         yield polarity ? (A < B) : (B <= A);
 0574            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0575            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0576            swapOperands = !polarity;
 0577            break;
 578          case BinaryExpr.ResolvedOpcode.EqCommon:  // A == B         yield polarity ? (A == B) : (A != B);
 0579            newOp = polarity ? BinaryExpr.Opcode.Eq : BinaryExpr.Opcode.Neq;
 0580            newROp = polarity ? BinaryExpr.ResolvedOpcode.EqCommon : BinaryExpr.ResolvedOpcode.NeqCommon;
 0581            swapOperands = false;
 0582            break;
 583          case BinaryExpr.ResolvedOpcode.NeqCommon:  // A != B         yield polarity ? (A != B) : (A == B);
 0584            newOp = polarity ? BinaryExpr.Opcode.Neq : BinaryExpr.Opcode.Eq;
 0585            newROp = polarity ? BinaryExpr.ResolvedOpcode.NeqCommon : BinaryExpr.ResolvedOpcode.EqCommon;
 0586            swapOperands = false;
 0587            break;
 588          case BinaryExpr.ResolvedOpcode.NotInSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0589            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0590            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSet : BinaryExpr.ResolvedOpcode.InSet;
 0591            swapOperands = false;
 0592            break;
 593          case BinaryExpr.ResolvedOpcode.NotInSeq:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0594            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0595            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSeq : BinaryExpr.ResolvedOpcode.InSeq;
 0596            swapOperands = false;
 0597            break;
 598          case BinaryExpr.ResolvedOpcode.NotInMultiSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0599            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0600            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMultiSet : BinaryExpr.ResolvedOpcode.InMultiSet;
 0601            swapOperands = false;
 0602            break;
 603          case BinaryExpr.ResolvedOpcode.NotInMap:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0604            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0605            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMap : BinaryExpr.ResolvedOpcode.InMap;
 0606            swapOperands = false;
 0607            break;
 608          default:
 0609            goto JUST_RETURN_IT;
 610        }
 0611        if (newROp != b.ResolvedOp || swapOperands) {
 0612          b = new BinaryExpr(b.tok, newOp, swapOperands ? b.E1 : b.E0, swapOperands ? b.E0 : b.E1);
 0613          b.ResolvedOp = newROp;
 0614          b.Type = Type.Bool;
 0615          yield return b;
 0616          yield break;
 617        }
 0618      }
 0619    JUST_RETURN_IT:;
 0620      if (polarity) {
 0621        yield return expr;
 0622      } else {
 0623        expr = new UnaryOpExpr(expr.tok, UnaryOpExpr.Opcode.Not, expr);
 0624        expr.Type = Type.Bool;
 0625        yield return expr;
 0626      }
 0627    }
 628
 629    /// <summary>
 630    /// If the return value is negative, the resulting "e0" and "e1" should not be used.
 631    /// Otherwise, the following is true on return:
 632    /// The new "e0 op e1" is equivalent to the old "e0 op e1".
 633    /// One of "e0" and "e1" is the identifier "boundVars[bvi]"; the return value is either 0 or 1, and indicates which.
 634    /// The other of "e0" and "e1" is an expression whose free variables are not among "boundVars[bvi..]".
 635    /// Ensures that the resulting "e0" and "e1" are not ConcreteSyntaxExpression's.
 636    /// </summary>
 637    static int SanitizeForBoundDiscovery<VT>(List<VT> boundVars, int bvi, BinaryExpr.ResolvedOpcode op,
 638      List<ComprehensionExpr.BoundedPool> knownBounds,
 0639      ref Expression e0, ref Expression e1) where VT : IVariable {
 640      Contract.Requires(boundVars != null);
 641      Contract.Requires(0 <= bvi && bvi < boundVars.Count);
 642      Contract.Requires(knownBounds != null);
 643      Contract.Requires(knownBounds.Count == boundVars.Count);
 644      Contract.Requires(e0 != null);
 645      Contract.Requires(e1 != null);
 646      Contract.Ensures(Contract.Result<int>() < 2);
 647      Contract.Ensures(!(Contract.ValueAtReturn(out e0) is ConcreteSyntaxExpression));
 648      Contract.Ensures(!(Contract.ValueAtReturn(out e1) is ConcreteSyntaxExpression));
 649
 0650      IVariable bv = boundVars[bvi];
 0651      e0 = e0.Resolved;
 0652      e1 = e1.Resolved;
 653
 654      // make an initial assessment of where bv is; to continue, we need bv to appear in exactly one operand
 0655      var fv0 = FreeVariables(e0);
 0656      var fv1 = FreeVariables(e1);
 657      Expression thisSide;
 658      Expression thatSide;
 659      int whereIsBv;
 0660      if (fv0.Contains(bv)) {
 0661        if (fv1.Contains(bv)) {
 0662          return -1;
 663        }
 0664        whereIsBv = 0;
 0665        thisSide = e0;
 0666        thatSide = e1;
 0667      } else if (fv1.Contains(bv)) {
 0668        whereIsBv = 1;
 0669        thisSide = e1;
 0670        thatSide = e0;
 0671      } else {
 0672        return -1;
 673      }
 674
 675      // Next, clean up the side where bv is by adjusting both sides of the expression
 0676      switch (op) {
 677        case BinaryExpr.ResolvedOpcode.EqCommon:
 678        case BinaryExpr.ResolvedOpcode.NeqCommon:
 679        case BinaryExpr.ResolvedOpcode.Gt:
 680        case BinaryExpr.ResolvedOpcode.Ge:
 681        case BinaryExpr.ResolvedOpcode.Le:
 682        case BinaryExpr.ResolvedOpcode.Lt:
 683          // Repeatedly move additive or subtractive terms from thisSide to thatSide
 0684          while (true) {
 0685            var bin = thisSide as BinaryExpr;
 0686            if (bin == null) {
 0687              break; // done simplifying
 688
 0689            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 690              // Change "A+B op C" into either "A op C-B" or "B op C-A", depending on where we find bv among A and B.
 0691              if (!FreeVariables(bin.E1).Contains(bv)) {
 0692                thisSide = bin.E0.Resolved;
 0693                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E1);
 0694              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 0695                thisSide = bin.E1.Resolved;
 0696                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E0);
 0697              } else {
 0698                break; // done simplifying
 699              }
 0700              ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0701              thatSide.Type = bin.Type;
 702
 0703            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 704              // Change "A-B op C" in a similar way.
 0705              if (!FreeVariables(bin.E1).Contains(bv)) {
 706                // change to "A op C+B"
 0707                thisSide = bin.E0.Resolved;
 0708                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Add, thatSide, bin.E1);
 0709                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Add;
 0710              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 711                // In principle, change to "-B op C-A" and then to "B dualOp A-C".  But since we don't want
 712                // to change "op", we instead end with "A-C op B" and switch the mapping of thisSide/thatSide
 713                // to e0/e1 (by inverting "whereIsBv").
 0714                thisSide = bin.E1.Resolved;
 0715                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, bin.E0, thatSide);
 0716                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0717                whereIsBv = 1 - whereIsBv;
 0718              } else {
 0719                break; // done simplifying
 720              }
 0721              thatSide.Type = bin.Type;
 722
 0723            } else {
 0724              break; // done simplifying
 725            }
 0726          }
 0727          break;
 728
 729        default:
 0730          break;
 731      }
 732      // our transformation above maintained the following invariant:
 0733      Contract.Assert(!FreeVariables(thatSide).Contains(bv));
 734
 735      // Now, see if the interesting side is simply bv itself
 0736      if (thisSide is IdentifierExpr && ((IdentifierExpr)thisSide).Var == bv) {
 737        // we're cool
 0738      } else {
 739        // no, the situation is more complicated than we care to understand
 0740        return -1;
 741      }
 742
 743      // Finally, check the bound variables of "thatSide". We allow "thatSide" to
 744      // depend on bound variables that are listed before "bv" (that is, a bound variable
 745      // "boundVars[k]" where "k < bvi"). By construction, "thatSide" does not depend
 746      // on "bv". Generally, for any bound variable "bj" that is listed after "bv"
 747      // (that is, "bj" is some "boundVars[j]" where "bvi < j"), we do not allow
 748      // "thatSide" to depend on "bv", but there is an important exception:
 749      // If
 750      //   *  "op" makes "thatSide" denote an integer upper bound on "bv" (or, analogously,
 751      //      a integer lower bound),
 752      //   *  "thatSide" depends on "bj",
 753      //   *  "thatSide" is monotonic in "bj",
 754      //   *  "bj" has a known integer upper bound "u",
 755      //   *  "u" does not depend on "bv" or any bound variable listed after "bv"
 756      //      (from the way we're constructing bounds, we already know that "u"
 757      //      does not depend on "bj" or any bound variable listed after "bj")
 758      // then we can substitute "u" for "bj" in "thatSide".
 759      // By going from right to left, we can make the rule above slightly more
 760      // liberal by considering a cascade of substitutions.
 0761      var fvThatSide = FreeVariables(thatSide);
 0762      for (int j = boundVars.Count; bvi + 1 <= --j;) {
 0763        if (fvThatSide.Contains(boundVars[j])) {
 0764          if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 0765            var jBounds = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 0766            Expression u = null;
 0767            if (op == BinaryExpr.ResolvedOpcode.Lt || op == BinaryExpr.ResolvedOpcode.Le) {
 0768              u = whereIsBv == 0 ? jBounds.UpperBound : jBounds.LowerBound;
 0769            } else if (op == BinaryExpr.ResolvedOpcode.Gt || op == BinaryExpr.ResolvedOpcode.Ge) {
 0770              u = whereIsBv == 0 ? jBounds.LowerBound : jBounds.UpperBound;
 0771            }
 0772            if (u != null && !FreeVariables(u).Contains(bv) && IsMonotonic(u, boundVars[j], true)) {
 0773              thatSide = Translator.Substitute(thatSide, boundVars[j], u);
 0774              fvThatSide = FreeVariables(thatSide);
 0775              continue;
 776            }
 0777          }
 0778          return -1; // forget about "bv OP thatSide"
 779        }
 0780      }
 781
 782      // As we return, also return the adjusted sides
 0783      if (whereIsBv == 0) {
 0784        e0 = thisSide;
 0785        e1 = thatSide;
 0786      } else {
 0787        e0 = thatSide;
 0788        e1 = thisSide;
 0789      }
 0790      return whereIsBv;
 0791    }
 792
 793    /// <summary>
 794    /// If "position", then returns "true" if "x" occurs only positively in "expr".
 795    /// If "!position", then returns "true" if "x" occurs only negatively in "expr".
 796    /// </summary>
 0797    public static bool IsMonotonic(Expression expr, IVariable x, bool position) {
 798      Contract.Requires(expr != null && expr.Type != null);
 799      Contract.Requires(x != null);
 800
 0801      if (expr is IdentifierExpr identifierExpr) {
 0802        return identifierExpr.Var != x || position;
 0803      } else if (expr is BinaryExpr binaryExpr) {
 0804        if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 0805          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, position);
 0806        } else if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 0807          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, !position);
 808        }
 0809      }
 0810      return !FreeVariables(expr).Contains(x);
 0811    }
 812  }
 813}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/NameResolutionAndTypeInference.cs

#LineLine coverage
 1#define TI_DEBUG_PRINT
 2//-----------------------------------------------------------------------------
 3//
 4// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 5// Copyright by the contributors to the Dafny Project
 6// SPDX-License-Identifier: MIT
 7//
 8//-----------------------------------------------------------------------------
 9using System;
 10using System.Collections.Generic;
 11using System.Linq;
 12using System.Numerics;
 13using System.Diagnostics.Contracts;
 14using System.IO;
 15using System.Reflection;
 16using JetBrains.Annotations;
 17using Microsoft.BaseTypes;
 18using Microsoft.Boogie;
 19using Microsoft.CodeAnalysis.CSharp.Syntax;
 20using Microsoft.Dafny.Plugins;
 21using static Microsoft.Dafny.ErrorRegistry;
 22
 23namespace Microsoft.Dafny {
 24  public partial class Resolver {
 25    /// <summary>
 26    /// There are two rounds of name resolution + type inference. The "initialRound" parameter says which one to do.
 27    /// </summary>
 249028    void ResolveNamesAndInferTypes(List<TopLevelDecl> declarations, bool initialRound) {
 2241029      foreach (TopLevelDecl topd in declarations) {
 498030        Contract.Assert(topd != null);
 498031        Contract.Assert(VisibleInScope(topd));
 498032        Contract.Assert(AllTypeConstraints.Count == 0);
 498033        Contract.Assert(currentClass == null);
 34
 498035        allTypeParameters.PushMarker();
 498036        ResolveTypeParameters(topd.TypeArgs, !initialRound, topd);
 37
 747038        if (initialRound) {
 249039          ResolveNamesAndInferTypesForOneDeclarationInitial(topd);
 498040        } else {
 249041          ResolveNamesAndInferTypesForOneDeclaration(topd);
 249042        }
 43
 498044        allTypeParameters.PopMarker();
 45
 498046        Contract.Assert(AllTypeConstraints.Count == 0);
 498047        Contract.Assert(currentClass == null);
 498048      }
 249049    }
 50
 51    /// <summary>
 52    /// Assumes type parameters of "topd" have already been pushed.
 53    /// </summary>
 249054    void ResolveNamesAndInferTypesForOneDeclarationInitial(TopLevelDecl topd) {
 249055      if (topd is NewtypeDecl newtypeDecl) {
 56        // this check can be done only after it has been determined that the redirected types do not involve cycles
 057        AddXConstraint(newtypeDecl.tok, "NumericType", newtypeDecl.BaseType, "newtypes must be based on some numeric typ
 58        // type check the constraint, if any
 059        if (newtypeDecl.Var != null) {
 060          Contract.Assert(object.ReferenceEquals(newtypeDecl.Var.Type, newtypeDecl.BaseType));  // follows from NewtypeD
 061          Contract.Assert(newtypeDecl.Constraint != null);  // follows from NewtypeDecl invariant
 62
 063          scope.PushMarker();
 064          scope.AllowInstance = false;
 065          var added = scope.Push(newtypeDecl.Var.Name, newtypeDecl.Var);
 066          Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 067          ResolveExpression(newtypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(newtypeDecl, true), fal
 068          Contract.Assert(newtypeDecl.Constraint.Type != null);  // follows from postcondition of ResolveExpression
 069          ConstrainTypeExprBool(newtypeDecl.Constraint, "newtype constraint must be of type bool (instead got {0})");
 070          scope.PopMarker();
 071        }
 072        SolveAllTypeConstraints();
 73
 332074      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 75        // type check the constraint
 83076        Contract.Assert(object.ReferenceEquals(subsetTypeDecl.Var.Type, subsetTypeDecl.Rhs)); // follows from SubsetType
 83077        Contract.Assert(subsetTypeDecl.Constraint != null); // follows from SubsetTypeDecl invariant
 83078        scope.PushMarker();
 83079        scope.AllowInstance = false;
 83080        var added = scope.Push(subsetTypeDecl.Var.Name, subsetTypeDecl.Var);
 83081        Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 83082        ResolveExpression(subsetTypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(subsetTypeDecl, true),
 83083        Contract.Assert(subsetTypeDecl.Constraint.Type != null); // follows from postcondition of ResolveExpression
 83084        ConstrainTypeExprBool(subsetTypeDecl.Constraint, "subset-type constraint must be of type bool (instead got {0})"
 83085        scope.PopMarker();
 83086        SolveAllTypeConstraints();
 83087      }
 88
 415089      if (topd is TopLevelDeclWithMembers cl) {
 166090        ResolveClassMemberBodiesInitial(cl);
 166091      }
 249092    }
 93
 249094    void ResolveNamesAndInferTypesForOneDeclaration(TopLevelDecl topd) {
 249095      if (topd is NewtypeDecl newtypeDecl) {
 096        if (newtypeDecl.Witness != null) {
 097          var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 098          scope.PushMarker();
 099          scope.AllowInstance = false;
 0100          ResolveExpression(newtypeDecl.Witness, new ResolutionContext(codeContext, false));
 0101          scope.PopMarker();
 0102          ConstrainSubtypeRelation(newtypeDecl.Var.Type, newtypeDecl.Witness.Type, newtypeDecl.Witness, "witness express
 0103        }
 0104        SolveAllTypeConstraints();
 105
 3320106      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 830107        if (subsetTypeDecl.Witness != null) {
 0108          var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Gh
 0109          scope.PushMarker();
 0110          scope.AllowInstance = false;
 0111          ResolveExpression(subsetTypeDecl.Witness, new ResolutionContext(codeContext, false));
 0112          scope.PopMarker();
 0113          ConstrainSubtypeRelation(subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type, subsetTypeDecl.Witness,
 0114            "witness expression must have type '{0}' (got '{1}')", subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type)
 0115        }
 830116        SolveAllTypeConstraints();
 117
 2490118      } else if (topd is IteratorDecl iteratorDecl) {
 0119        ResolveIterator(iteratorDecl);
 120
 1660121      } else if (topd is DatatypeDecl dt) {
 122        // resolve any default parameters
 0123        foreach (var ctor in dt.Ctors) {
 0124          scope.PushMarker();
 0125          scope.AllowInstance = false;
 0126          ctor.Formals.ForEach(p => scope.Push(p.Name, p));
 0127          ResolveAttributes(ctor, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 0128          ResolveParameterDefaultValues(ctor.Formals, ResolutionContext.FromCodeContext(dt));
 0129          scope.PopMarker();
 0130        }
 0131      }
 132
 4150133      if (topd is TopLevelDeclWithMembers cl) {
 1660134        ResolveClassMemberBodies(cl);
 1660135      }
 136
 137      // resolve attributes
 2490138      scope.PushMarker();
 2490139      Contract.Assert(currentClass == null);
 2490140      scope.AllowInstance = false;
 2490141      if (topd is IteratorDecl iter) {
 0142        iter.Ins.ForEach(p => scope.Push(p.Name, p));
 0143      }
 2490144      ResolveAttributes(topd, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 2490145      scope.PopMarker();
 2490146    }
 147
 38390148    void EagerAddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 149      Contract.Requires(tok != null);
 150      Contract.Requires(lhs != null);
 151      Contract.Requires(rhs != null);
 152      Contract.Requires(errMsgFormat != null);
 38390153      var lhsNormalized = lhs.Normalize();
 38390154      var rhsNormalized = rhs.Normalize();
 50430155      if (lhsNormalized is TypeProxy lhsProxy && !(rhsNormalized is TypeProxy)) {
 12040156        Contract.Assert(lhsProxy.T == null); // otherwise, lhs.Normalize() above would have kept on going
 12040157        AssignProxyAndHandleItsConstraints(lhsProxy, rhsNormalized, true);
 38390158      } else {
 26350159        AddAssignableConstraint(tok, lhs, rhs, errMsgFormat);
 26350160      }
 38390161    }
 789700162    public void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 163      Contract.Requires(tok != null);
 164      Contract.Requires(lhs != null);
 165      Contract.Requires(rhs != null);
 166      Contract.Requires(errMsgFormat != null);
 789700167      AddXConstraint(tok, "Assignable", lhs, rhs, errMsgFormat);
 789700168    }
 79110169    private void AddXConstraint(IToken tok, string constraintName, Type type, string errMsgFormat) {
 170      Contract.Requires(tok != null);
 171      Contract.Requires(constraintName != null);
 172      Contract.Requires(type != null);
 173      Contract.Requires(errMsgFormat != null);
 79110174      var types = new Type[] { type };
 79110175      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 79110176    }
 365380177    void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, TypeConstraint.ErrorMsg errMsg) {
 178      Contract.Requires(tok != null);
 179      Contract.Requires(lhs != null);
 180      Contract.Requires(rhs != null);
 181      Contract.Requires(errMsg != null);
 365380182      AddXConstraint(tok, "Assignable", lhs, rhs, errMsg);
 365380183    }
 430184    private void AddXConstraint(IToken tok, string constraintName, Type type, TypeConstraint.ErrorMsg errMsg) {
 185      Contract.Requires(tok != null);
 186      Contract.Requires(constraintName != null);
 187      Contract.Requires(type != null);
 188      Contract.Requires(errMsg != null);
 430189      var types = new Type[] { type };
 430190      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 430191    }
 847630192    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, string errMsgFormat) {
 193      Contract.Requires(tok != null);
 194      Contract.Requires(constraintName != null);
 195      Contract.Requires(type0 != null);
 196      Contract.Requires(type1 != null);
 197      Contract.Requires(errMsgFormat != null);
 847630198      var types = new Type[] { type0, type1 };
 847630199      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 847630200    }
 368330201    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, TypeConstraint.ErrorMsg errMs
 202      Contract.Requires(tok != null);
 203      Contract.Requires(constraintName != null);
 204      Contract.Requires(type0 != null);
 205      Contract.Requires(type1 != null);
 206      Contract.Requires(errMsg != null);
 368330207      var types = new Type[] { type0, type1 };
 368330208      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 368330209    }
 1260210    private void AddXConstraint(IToken tok, string constraintName, Type type, Expression expr0, Expression expr1, string
 211      Contract.Requires(tok != null);
 212      Contract.Requires(constraintName != null);
 213      Contract.Requires(type != null);
 214      Contract.Requires(expr0 != null);
 215      Contract.Requires(expr1 != null);
 216      Contract.Requires(errMsgFormat != null);
 1260217      var types = new Type[] { type };
 1260218      var exprs = new Expression[] { expr0, expr1 };
 1260219      AllXConstraints.Add(new XConstraintWithExprs(tok, constraintName, types, exprs, new TypeConstraint.ErrorMsgWithTok
 1260220    }
 221
 222    [System.Diagnostics.Conditional("TI_DEBUG_PRINT")]
 2062550223    void PrintTypeConstraintState(int lbl) {
 4125100224      if (!Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 2062550225        return;
 226      }
 0227      Options.OutputWriter.WriteLine("DEBUG: ---------- type constraints ---------- {0} {1}", lbl, lbl == 0 && currentMe
 0228      foreach (var constraint in AllTypeConstraints) {
 0229        var super = constraint.Super.Normalize();
 0230        var sub = constraint.Sub.Normalize();
 0231        Options.OutputWriter.WriteLine("    {0} :> {1}", super is IntVarietiesSupertype ? "int-like" : super is RealVari
 0232      }
 0233      foreach (var xc in AllXConstraints) {
 0234        Options.OutputWriter.WriteLine("    {0}", xc);
 0235      }
 0236      Options.OutputWriter.WriteLine();
 0237      if (lbl % 2 == 1) {
 0238        Options.OutputWriter.WriteLine("DEBUG: --------------------------------------");
 0239      }
 2062550240    }
 241
 242    /// <summary>
 243    /// Attempts to fully solve all type constraints.
 244    /// Upon failure, reports errors.
 245    /// Clears all constraints.
 246    /// </summary>
 77275247    public void SolveAllTypeConstraints() {
 77275248      PrintTypeConstraintState(0);
 77275249      PartiallySolveTypeConstraints(true);
 77275250      PrintTypeConstraintState(1);
 231825251      foreach (var constraint in AllTypeConstraints) {
 0252        if (Type.IsSupertype(constraint.Super, constraint.Sub)) {
 253          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more sub-typin
 0254          Contract.Assume(false, string.Format("DEBUG: Unexpectedly satisfied supertype relation ({0} :> {1}) |||| ", co
 0255        } else {
 0256          constraint.FlagAsError(this);
 0257        }
 0258      }
 231825259      foreach (var xc in AllXConstraints) {
 0260        if (xc.Confirm(this, true, out var convertedIntoOtherTypeConstraints, out var moreXConstraints)) {
 261          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more XConstrai
 0262          Contract.Assume(false, string.Format("DEBUG: Unexpectedly confirmed XConstraint: {0} |||| ", xc));
 0263        } else if (xc.CouldBeAnything()) {
 264          // suppress the error message; it will later be flagged as an underspecified type
 0265        } else {
 0266          xc.errorMsg.FlagAsError(this);
 0267        }
 0268      }
 77275269      TypeConstraint.ReportErrors(this, reporter);
 77275270      AllTypeConstraints.Clear();
 77275271      AllXConstraints.Clear();
 77275272    }
 273
 274    /// <summary>
 275    /// Adds type constraints for the expressions in the given attributes.
 276    ///
 277    /// If "solveConstraints" is "true", then the constraints are also solved. In this case, it is assumed on entry that
 278    /// prior type constraints. That is, the only type constraints being solved for are the ones in the given attributes
 279    /// </summary>
 2012235280    public void ResolveAttributes(IAttributeBearingDeclaration attributeHost, ResolutionContext resolutionContext, bool 
 281      Contract.Requires(resolutionContext != null);
 282      Contract.Requires(attributeHost != null);
 283
 2012235284      Contract.Assume(!solveConstraints || AllTypeConstraints.Count == 0);
 285
 286      // order does not matter much for resolution, so resolve them in reverse order
 6041685287      foreach (var attr in attributeHost.Attributes.AsEnumerable()) {
 1660288        if (attr is UserSuppliedAttributes) {
 0289          var usa = (UserSuppliedAttributes)attr;
 0290          usa.Recognized = IsRecognizedAttribute(usa, attributeHost);
 0291        }
 3320292        if (attr.Args != null) {
 7470293          foreach (var arg in attr.Args) {
 830294            Contract.Assert(arg != null);
 830295            ResolveExpression(arg, resolutionContext);
 830296          }
 1660297        }
 1660298      }
 299
 2033940300      if (solveConstraints) {
 21705301        SolveAllTypeConstraints();
 21705302      }
 2012235303    }
 304
 305    /// <summary>
 306    /// "IsTwoState" implies that "old" and "fresh" expressions are allowed.
 307    /// </summary>
 2713225308    public void ResolveExpression(Expression expr, ResolutionContext resolutionContext) {
 309
 310#if TEST_TYPE_SYNONYM_TRANSPARENCY
 311      ResolveExpressionX(expr, resolutionContext);
 312      // For testing purposes, change the type of "expr" to a type synonym (mwo-ha-ha-ha!)
 313      var t = expr.Type;
 314      Contract.Assert(t != null);
 315      var sd = new TypeSynonymDecl(expr.tok, "type#synonym#transparency#test", new TypeParameter.TypeParameterCharacteri
 316        new List<TypeParameter>(), resolutionContext.CodeContext.EnclosingModule, t, null);
 317      var ts = new UserDefinedType(expr.tok, "type#synonym#transparency#test", sd, new List<Type>(), null);
 318      expr.DebugTest_ChangeType(ts);
 319    }
 320    public void ResolveExpressionX(Expression expr, ResolutionContext resolutionContext) {
 321#endif
 322      Contract.Requires(expr != null);
 323      Contract.Requires(resolutionContext != null);
 324      Contract.Ensures(expr.Type != null);
 3827270325      if (expr.Type != null) {
 326        // expression has already been resolved
 1114045327        return;
 328      }
 1599180329      DominatingStatementLabels.PushMarker();
 330
 331      // The following cases will resolve the subexpressions and will attempt to assign a type of expr.  However, if err
 332      // and it cannot be determined what the type of expr is, then it is fine to leave expr.Type as null.  In that case
 333      // of this method will assign proxy type to the expression, which reduces the number of error messages that are pr
 334      // while type checking the rest of the program.
 335
 1626915336      if (expr is ParensExpression) {
 27735337        var e = (ParensExpression)expr;
 27735338        ResolveExpression(e.E, resolutionContext);
 27735339        var innerRange = e.E.RangeToken;
 27735340        e.ResolvedExpression = e.E; // Overwrites the range, which is not suitable for ParensExpressions
 27735341        e.E.RangeToken = innerRange;
 27735342        e.Type = e.E.Type;
 343
 1605630344      } else if (expr is ChainingExpression) {
 6450345        var e = (ChainingExpression)expr;
 6450346        ResolveExpression(e.E, resolutionContext);
 6450347        e.ResolvedExpression = e.E;
 6450348        e.Type = e.E.Type;
 349
 1608455350      } else if (expr is NegationExpression) {
 37010351        var e = (NegationExpression)expr;
 37010352        ResolveExpression(e.E, resolutionContext);
 37010353        e.Type = e.E.Type;
 37010354        AddXConstraint(e.E.tok, "NumericOrBitvector", e.E.Type, "type of unary - must be of a numeric or bitvector type 
 355        // Note, e.ResolvedExpression will be filled in during CheckTypeInference, at which time e.Type has been determi
 356
 1870375357      } else if (expr is LiteralExpr) {
 305380358        LiteralExpr e = (LiteralExpr)expr;
 359
 305380360        if (e is StaticReceiverExpr) {
 0361          StaticReceiverExpr eStatic = (StaticReceiverExpr)e;
 0362          ResolveType(eStatic.tok, eStatic.UnresolvedType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, nu
 0363          eStatic.Type = eStatic.UnresolvedType;
 305380364        } else {
 306210365          if (e.Value == null) {
 830366            e.Type = new InferredTypeProxy();
 830367            AddXConstraint(e.tok, "IsNullableRefType", e.Type, "type of 'null' is a reference type, but it is used as {0
 393340368          } else if (e.Value is BigInteger) {
 87960369            var proxy = new InferredTypeProxy();
 87960370            e.Type = proxy;
 87960371            ConstrainSubtypeRelation(new IntVarietiesSupertype(), e.Type, e.tok, "integer literal used as if it had type
 304550372          } else if (e.Value is BaseTypes.BigDec) {
 0373            var proxy = new InferredTypeProxy();
 0374            e.Type = proxy;
 0375            ConstrainSubtypeRelation(new RealVarietiesSupertype(), e.Type, e.tok, "type of real literal is used as {0}",
 296150376          } else if (e.Value is bool) {
 79560377            e.Type = Type.Bool;
 288650378          } else if (e is CharLiteralExpr) {
 72060379            e.Type = Type.Char;
 202000380          } else if (e is StringLiteralExpr) {
 64970381            e.Type = Type.String();
 64970382            ResolveType(e.tok, e.Type, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 64970383          } else {
 0384            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected literal type
 385          }
 305380386        }
 1527985387      } else if (expr is ThisExpr) {
 0388        if (!scope.AllowInstance) {
 0389          reporter.Error(MessageSource.Resolver, expr, "'this' is not allowed in a 'static' context");
 0390        }
 0391        if (currentClass is ClassDecl cd && cd.IsDefaultClass) {
 392          // there's no type
 0393        } else {
 0394          if (currentClass == null) {
 0395            Contract.Assert(reporter.HasErrors);
 0396          } else {
 0397            expr.Type = GetThisType(expr.tok, currentClass);  // do this regardless of scope.AllowInstance, for better e
 0398          }
 0399        }
 400
 1222605401      } else if (expr is IdentifierExpr) {
 0402        var e = (IdentifierExpr)expr;
 0403        e.Var = scope.Find(e.Name);
 0404        if (e.Var != null) {
 0405          expr.Type = e.Var.Type;
 0406        } else {
 0407          reporter.Error(MessageSource.Resolver, expr, "Identifier does not denote a local variable, parameter, or bound
 0408        }
 409
 1382345410      } else if (expr is DatatypeValue) {
 159740411        DatatypeValue dtv = (DatatypeValue)expr;
 159740412        if (!moduleInfo.TopLevels.TryGetValue(dtv.DatatypeName, out var d)) {
 0413          reporter.Error(MessageSource.Resolver, expr.tok, "Undeclared datatype: {0}", dtv.DatatypeName);
 159740414        } else if (d is AmbiguousTopLevelDecl) {
 0415          var ad = (AmbiguousTopLevelDecl)d;
 0416          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 159740417        } else if (!(d is DatatypeDecl)) {
 0418          reporter.Error(MessageSource.Resolver, expr.tok, "Expected datatype: {0}", dtv.DatatypeName);
 159740419        } else {
 159740420          ResolveDatatypeValue(resolutionContext, dtv, (DatatypeDecl)d, null);
 159740421        }
 422
 1371075423      } else if (expr is DisplayExpression) {
 148470424        DisplayExpression e = (DisplayExpression)expr;
 148470425        Type elementType = new InferredTypeProxy() { KeepConstraints = true };
 1534380426        foreach (Expression ee in e.Elements) {
 362990427          ResolveExpression(ee, resolutionContext);
 362990428          Contract.Assert(ee.Type != null);  // follows from postcondition of ResolveExpression
 362990429          ConstrainSubtypeRelation(elementType, ee.Type, ee.tok, "All elements of display must have some common supertyp
 362990430        }
 196740431        if (expr is SetDisplayExpr) {
 48270432          var se = (SetDisplayExpr)expr;
 48270433          expr.Type = new SetType(se.Finite, elementType);
 193930434        } else if (expr is MultiSetDisplayExpr) {
 45460435          expr.Type = new MultiSetType(elementType);
 100200436        } else {
 54740437          expr.Type = new SeqType(elementType);
 54740438        }
 1062865439      } else if (expr is MapDisplayExpr) {
 0440        MapDisplayExpr e = (MapDisplayExpr)expr;
 0441        Type domainType = new InferredTypeProxy();
 0442        Type rangeType = new InferredTypeProxy();
 0443        foreach (ExpressionPair p in e.Elements) {
 0444          ResolveExpression(p.A, resolutionContext);
 0445          Contract.Assert(p.A.Type != null);  // follows from postcondition of ResolveExpression
 0446          ConstrainSubtypeRelation(domainType, p.A.Type, p.A.tok, "All elements of display must have some common superty
 0447          ResolveExpression(p.B, resolutionContext);
 0448          Contract.Assert(p.B.Type != null);  // follows from postcondition of ResolveExpression
 0449          ConstrainSubtypeRelation(rangeType, p.B.Type, p.B.tok, "All elements of display must have some common supertyp
 0450        }
 0451        expr.Type = new MapType(e.Finite, domainType, rangeType);
 1674340452      } else if (expr is NameSegment) {
 759945453        var e = (NameSegment)expr;
 759945454        ResolveNameSegment(e, true, null, resolutionContext, false);
 455
 759945456        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0457          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.Name);
 0458          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 759945459        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0460          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.Name);
 0461          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0462        }
 463
 921565464      } else if (expr is ExprDotName) {
 7170465        var e = (ExprDotName)expr;
 7170466        ResolveDotSuffix(e, true, null, resolutionContext, false);
 7170467        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0468          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.SuffixName);
 0469          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 7170470        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0471          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.SuffixName);
 0472          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0473        }
 474
 161680475      } else if (expr is ApplySuffix) {
 7230476        var e = (ApplySuffix)expr;
 7230477        ResolveApplySuffix(e, resolutionContext, false);
 478
 147280479      } else if (expr is MemberSelectExpr) {
 0480        var e = (MemberSelectExpr)expr;
 0481        ResolveExpression(e.Obj, resolutionContext);
 0482        Contract.Assert(e.Obj.Type != null);  // follows from postcondition of ResolveExpression
 0483        var member = ResolveMember(expr.tok, e.Obj.Type, e.MemberName, out var tentativeReceiverType);
 0484        if (member == null) {
 485          // error has already been reported by ResolveMember
 0486        } else if (member is Function) {
 0487          var fn = member as Function;
 0488          e.Member = fn;
 0489          if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 0490            reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context"
 0491          }
 492          // build the type substitution map
 0493          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0494          e.TypeApplication_JustMember = new List<Type>();
 495          Dictionary<TypeParameter, Type> subst;
 0496          var ctype = tentativeReceiverType as UserDefinedType;
 0497          if (ctype == null) {
 0498            subst = new Dictionary<TypeParameter, Type>();
 0499          } else {
 0500            subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0501          }
 0502          foreach (var tp in fn.TypeArgs) {
 0503            Type prox = new InferredTypeProxy();
 0504            subst[tp] = prox;
 0505            e.TypeApplication_JustMember.Add(prox);
 0506          }
 0507          subst = BuildTypeArgumentSubstitute(subst);
 0508          e.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 0509        } else if (member is Field) {
 0510          var field = (Field)member;
 0511          e.Member = field;
 0512          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0513          e.TypeApplication_JustMember = new List<Type>();
 0514          if (e.Obj is StaticReceiverExpr && !field.IsStatic) {
 0515            reporter.Error(MessageSource.Resolver, expr, "a field must be selected via an object, not just a class name"
 0516          }
 0517          var ctype = tentativeReceiverType as UserDefinedType;
 0518          if (ctype == null) {
 0519            e.Type = field.Type;
 0520          } else {
 0521            Contract.Assert(ctype.ResolvedClass != null); // follows from postcondition of ResolveMember
 522            // build the type substitution map
 0523            var subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0524            e.Type = field.Type.Subst(subst);
 0525          }
 0526        } else {
 0527          reporter.Error(MessageSource.Resolver, expr, "member {0} in type {1} does not refer to a field or a function",
 0528        }
 529
 152960530      } else if (expr is SeqSelectExpr) {
 12910531        SeqSelectExpr e = (SeqSelectExpr)expr;
 12910532        ResolveSeqSelectExpr(e, resolutionContext);
 533
 140050534      } else if (expr is MultiSelectExpr) {
 0535        MultiSelectExpr e = (MultiSelectExpr)expr;
 536
 0537        ResolveExpression(e.Array, resolutionContext);
 0538        Contract.Assert(e.Array.Type != null);  // follows from postcondition of ResolveExpression
 0539        Contract.Assert(e.Array.Type.TypeArgs != null);  // if it is null, should make a 1-element list with a Proxy
 0540        Type elementType = e.Array.Type.TypeArgs.Count > 0 ?
 0541          e.Array.Type.TypeArgs[0] :
 0542          new InferredTypeProxy();
 0543        ConstrainSubtypeRelation(ResolvedArrayType(e.Array.tok, e.Indices.Count, elementType, resolutionContext, true), 
 0544          "array selection requires an array{0} (got {1})", e.Indices.Count, e.Array.Type);
 0545        int i = 0;
 0546        foreach (Expression idx in e.Indices) {
 0547          Contract.Assert(idx != null);
 0548          ResolveExpression(idx, resolutionContext);
 0549          Contract.Assert(idx.Type != null);  // follows from postcondition of ResolveExpression
 0550          ConstrainToIntegerType(idx, true, "array selection requires integer- or bitvector-based numeric indices (got {
 0551          i++;
 0552        }
 0553        e.Type = elementType;
 554
 128400555      } else if (expr is SeqUpdateExpr) {
 1260556        SeqUpdateExpr e = (SeqUpdateExpr)expr;
 1260557        ResolveExpression(e.Seq, resolutionContext);
 1260558        Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 1260559        ResolveExpression(e.Index, resolutionContext);
 1260560        ResolveExpression(e.Value, resolutionContext);
 1260561        AddXConstraint(expr.tok, "SeqUpdatable", e.Seq.Type, e.Index, e.Value, "update requires a sequence, map, or mult
 1260562        expr.Type = new InferredTypeProxy(); // drop type constraints
 1260563        ConstrainSubtypeRelation(
 1260564          super: expr.Type, sub: e.Seq.Type, // expr.Type generalizes e.Seq.Type by dropping constraints
 1260565          exprForToken: expr,
 1260566          msg: "Update expression used with type '{0}'", e.Seq.Type);
 127140567      } else if (expr is DatatypeUpdateExpr) {
 0568        var e = (DatatypeUpdateExpr)expr;
 0569        ResolveExpression(e.Root, resolutionContext);
 0570        var ty = PartiallyResolveTypeForMemberSelection(expr.tok, e.Root.Type);
 0571        if (!ty.IsDatatype) {
 0572          reporter.Error(MessageSource.Resolver, expr, "datatype update expression requires a root expression of a datat
 0573        } else {
 0574          var (ghostLet, compiledLet) = ResolveDatatypeUpdate(expr.tok, e.Root, ty.AsDatatype, e.Updates, resolutionCont
 0575            out var members, out var legalSourceConstructors);
 0576          Contract.Assert((ghostLet == null) == (compiledLet == null));
 0577          if (ghostLet != null) {
 0578            e.ResolvedExpression = ghostLet; // this might be replaced by e.ResolvedCompiledExpression in CheckIsCompila
 0579            e.ResolvedCompiledExpression = compiledLet;
 0580            e.Members = members;
 0581            e.LegalSourceConstructors = legalSourceConstructors;
 0582            expr.Type = ghostLet.Type;
 0583          }
 0584        }
 585
 125880586      } else if (expr is FunctionCallExpr) {
 0587        var e = (FunctionCallExpr)expr;
 0588        ResolveFunctionCallExpr(e, resolutionContext);
 589
 125880590      } else if (expr is ApplyExpr) {
 0591        var e = (ApplyExpr)expr;
 0592        ResolveExpression(e.Function, resolutionContext);
 0593        foreach (var arg in e.Args) {
 0594          ResolveExpression(arg, resolutionContext);
 0595        }
 596
 597        // TODO: the following should be replaced by a type-class constraint that constrains the types of e.Function, e.
 0598        var fnType = e.Function.Type.AsArrowType;
 0599        if (fnType == null) {
 0600          reporter.Error(MessageSource.Resolver, e.tok,
 0601            "non-function expression (of type {0}) is called with parameters", e.Function.Type);
 0602        } else if (fnType.Arity != e.Args.Count) {
 0603          reporter.Error(MessageSource.Resolver, e.tok,
 0604            "wrong number of arguments to function application (function type '{0}' expects {1}, got {2})", fnType,
 0605            fnType.Arity, e.Args.Count);
 0606        } else {
 0607          for (var i = 0; i < fnType.Arity; i++) {
 0608            AddAssignableConstraint(e.Args[i].tok, fnType.Args[i], e.Args[i].Type,
 0609              "type mismatch for argument" + (fnType.Arity == 1 ? "" : " " + i) + " (function expects {0}, got {1})");
 0610          }
 0611        }
 612
 0613        expr.Type = fnType == null ? new InferredTypeProxy() : fnType.Result;
 614
 125880615      } else if (expr is SeqConstructionExpr) {
 0616        var e = (SeqConstructionExpr)expr;
 0617        var elementType = e.ExplicitElementType ?? new InferredTypeProxy();
 0618        ResolveType(e.tok, elementType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0619        ResolveExpression(e.N, resolutionContext);
 0620        ConstrainToIntegerType(e.N, false, "sequence construction must use an integer-based expression for the sequence 
 0621        ResolveExpression(e.Initializer, resolutionContext);
 0622        var arrowType = new ArrowType(e.tok, builtIns.ArrowTypeDecls[1], new List<Type>() { builtIns.Nat() }, elementTyp
 0623        var hintString = " (perhaps write '_ =>' in front of the expression you gave in order to make it an arrow type)"
 0624        ConstrainSubtypeRelation(arrowType, e.Initializer.Type, e.Initializer, "sequence-construction initializer expres
 0625          arrowType, e.Initializer.Type, new LazyString_OnTypeEquals(elementType, e.Initializer.Type, hintString));
 0626        expr.Type = new SeqType(elementType);
 627
 126200628      } else if (expr is MultiSetFormingExpr) {
 320629        MultiSetFormingExpr e = (MultiSetFormingExpr)expr;
 320630        ResolveExpression(e.E, resolutionContext);
 320631        var elementType = new InferredTypeProxy();
 320632        AddXConstraint(e.E.tok, "MultiSetConvertible", e.E.Type, elementType, "can only form a multiset from a seq or se
 320633        expr.Type = new MultiSetType(elementType);
 634
 125880635      } else if (expr is OldExpr) {
 0636        var e = (OldExpr)expr;
 0637        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "old", resolutionContext);
 0638        ResolveExpression(e.E, new ResolutionContext(resolutionContext.CodeContext, false) with { InOld = true });
 0639        expr.Type = e.E.Type;
 640
 125560641      } else if (expr is UnchangedExpr) {
 0642        var e = (UnchangedExpr)expr;
 0643        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "unchanged", resolutionContext);
 0644        foreach (var fe in e.Frame) {
 0645          ResolveFrameExpression(fe, FrameExpressionUse.Unchanged, resolutionContext);
 0646        }
 0647        expr.Type = Type.Bool;
 648
 125560649      } else if (expr is FreshExpr) {
 0650        var e = (FreshExpr)expr;
 0651        ResolveExpression(e.E, resolutionContext);
 0652        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "fresh", resolutionContext);
 653        // the type of e.E must be either an object or a set/seq of objects
 0654        AddXConstraint(expr.tok, "Freshable", e.E.Type, "the argument of a fresh expression must denote an object or a s
 0655        expr.Type = Type.Bool;
 656
 134900657      } else if (expr is UnaryOpExpr) {
 9340658        var e = (UnaryOpExpr)expr;
 9340659        ResolveExpression(e.E, resolutionContext);
 9340660        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 9340661        switch (e.Op) {
 662          case UnaryOpExpr.Opcode.Not:
 350663            AddXConstraint(e.E.tok, "BooleanBits", e.E.Type, "logical/bitwise negation expects a boolean or bitvector ar
 350664            expr.Type = e.E.Type;
 350665            break;
 666          case UnaryOpExpr.Opcode.Cardinality:
 8990667            AddXConstraint(expr.tok, "Sizeable", e.E.Type, "size operator expects a collection argument (instead got {0}
 8990668            expr.Type = Type.Int;
 8990669            break;
 670          case UnaryOpExpr.Opcode.Allocated:
 671            // the argument is allowed to have any type at all
 0672            expr.Type = Type.Bool;
 0673            if (2 <= Options.Allocated &&
 0674              ((resolutionContext.CodeContext is Function && !resolutionContext.InOld) || resolutionContext.CodeContext 
 0675              var declKind = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) is RedirectingTypeDecl redir ? red
 0676              reporter.Error(MessageSource.Resolver, expr, "a {0} definition is not allowed to depend on the set of allo
 0677            }
 0678            break;
 679          default:
 0680            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected unary operator
 681        }
 682
 683        // We do not have enough information to compute `e.ResolvedOp` yet.
 684        // For binary operators the computation happens in `CheckTypeInference`.
 685        // For unary operators it happens lazily in the getter of `e.ResolvedOp`.
 126370686      } else if (expr is ConversionExpr) {
 810687        var e = (ConversionExpr)expr;
 810688        ResolveExpression(e.E, resolutionContext);
 810689        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 810690        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 1620691        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 1620692          if (e.ToType.IsNumericBased(Type.NumericPersuasion.Int)) {
 810693            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an int-based typ
 810694          } else if (e.ToType.IsNumericBased(Type.NumericPersuasion.Real)) {
 0695            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a real-based typ
 0696          } else if (e.ToType.IsBitVectorType) {
 0697            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a bitvector-base
 0698          } else if (e.ToType.IsCharType) {
 0699            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a char type is a
 0700          } else if (e.ToType.IsBigOrdinalType) {
 0701            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an ORDINAL type 
 0702          } else if (e.ToType.IsRefType) {
 0703            AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type cast to reference type '{0}' must be from an exp
 0704          } else {
 0705            reporter.Error(MessageSource.Resolver, expr, "type conversions are not supported to this type (got {0})", e.
 0706          }
 810707          e.Type = e.ToType;
 810708        } else {
 0709          e.Type = new InferredTypeProxy();
 0710        }
 711
 116220712      } else if (expr is TypeTestExpr) {
 0713        var e = (TypeTestExpr)expr;
 0714        ResolveExpression(e.E, resolutionContext);
 0715        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 0716        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 0717        AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type test for type '{0}' must be from an expression assig
 0718        e.Type = Type.Bool;
 719
 177970720      } else if (expr is BinaryExpr) {
 721
 62560722        BinaryExpr e = (BinaryExpr)expr;
 62560723        ResolveExpression(e.E0, resolutionContext);
 62560724        Contract.Assert(e.E0.Type != null);  // follows from postcondition of ResolveExpression
 62560725        ResolveExpression(e.E1, resolutionContext);
 62560726        Contract.Assert(e.E1.Type != null);  // follows from postcondition of ResolveExpression
 727
 62560728        switch (e.Op) {
 729          case BinaryExpr.Opcode.Iff:
 730          case BinaryExpr.Opcode.Imp:
 731          case BinaryExpr.Opcode.Exp:
 732          case BinaryExpr.Opcode.And:
 16250733          case BinaryExpr.Opcode.Or: {
 16250734              ConstrainSubtypeRelation(Type.Bool, e.E0.Type, expr, "first argument to {0} must be of type bool (instead 
 16250735              var secondArgumentDescription = e.E1.tok is QuantifiedVariableRangeToken
 16250736                ? "range of quantified variable" : "second argument to {0}";
 16250737              ConstrainSubtypeRelation(Type.Bool, e.E1.Type, expr, secondArgumentDescription + " must be of type bool (i
 16250738              expr.Type = Type.Bool;
 16250739              break;
 740            }
 741
 742          case BinaryExpr.Opcode.Eq:
 743          case BinaryExpr.Opcode.Neq:
 2920744            AddXConstraint(expr.tok, "Equatable", e.E0.Type, e.E1.Type, "arguments must have comparable types (got {0} a
 2920745            expr.Type = Type.Bool;
 2920746            break;
 747
 748          case BinaryExpr.Opcode.Disjoint:
 1380749            Type disjointArgumentsType = new InferredTypeProxy();
 1380750            ConstrainSubtypeRelation(disjointArgumentsType, e.E0.Type, expr, "arguments to {2} must have a common supert
 1380751            ConstrainSubtypeRelation(disjointArgumentsType, e.E1.Type, expr, "arguments to {2} must have a common supert
 1380752            AddXConstraint(expr.tok, "Disjointable", disjointArgumentsType, "arguments must be of a set or multiset type
 1380753            expr.Type = Type.Bool;
 1380754            break;
 755
 756          case BinaryExpr.Opcode.Lt:
 22180757          case BinaryExpr.Opcode.Le: {
 22180758              if (e.Op == BinaryExpr.Opcode.Lt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0759                AddXConstraint(expr.tok, "RankOrderable", e.E0.Type, e.E1.Type, "arguments to rank comparison must be da
 0760                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankLt;
 22180761              } else {
 22180762                var cmpType = new InferredTypeProxy();
 22180763                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 22180764                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 22180765                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 22180766                AddXConstraint(expr.tok, "Orderable_Lt", e.E0.Type, e.E1.Type,
 22180767                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 22180768              }
 22180769              expr.Type = Type.Bool;
 22180770            }
 22180771            break;
 772
 773          case BinaryExpr.Opcode.Gt:
 1340774          case BinaryExpr.Opcode.Ge: {
 1340775              if (e.Op == BinaryExpr.Opcode.Gt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0776                AddXConstraint(expr.tok, "RankOrderable", e.E1.Type, e.E0.Type, "arguments to rank comparison must be da
 0777                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankGt;
 1340778              } else {
 1340779                var cmpType = new InferredTypeProxy();
 1340780                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 1340781                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 1340782                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 1340783                AddXConstraint(expr.tok, "Orderable_Gt", e.E0.Type, e.E1.Type,
 1340784                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 1340785              }
 1340786              expr.Type = Type.Bool;
 1340787            }
 1340788            break;
 789
 790          case BinaryExpr.Opcode.LeftShift:
 0791          case BinaryExpr.Opcode.RightShift: {
 0792              expr.Type = new InferredTypeProxy();
 0793              AddXConstraint(e.tok, "IsBitvector", expr.Type, "type of " + BinaryExpr.OpcodeString(e.Op) + " must be a b
 0794              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to " + BinaryExpr.OpcodeSt
 0795              AddXConstraint(expr.tok, "IntLikeOrBitvector", e.E1.Type, "type of right argument to " + BinaryExpr.Opcode
 0796            }
 0797            break;
 798
 13140799          case BinaryExpr.Opcode.Add: {
 13140800              expr.Type = new InferredTypeProxy();
 13140801              AddXConstraint(e.tok, "Plussable", expr.Type, "type of + must be of a numeric type, a bitvector type, ORDI
 13140802              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to + ({0}) must agree with
 13140803              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to + ({0}) must agree wit
 13140804            }
 13140805            break;
 806
 1280807          case BinaryExpr.Opcode.Sub: {
 1280808              expr.Type = new InferredTypeProxy();
 1280809              AddXConstraint(e.tok, "Minusable", expr.Type, "type of - must be of a numeric type, bitvector type, ORDINA
 1280810              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to - ({0}) must agree with
 811              // The following handles map subtraction, but does not in an unfortunately restrictive way.
 812              // First, it would be nice to delay the decision of it this is a map subtraction or not. This settles
 813              // for the simple way to decide based on what is currently known about the result type, which is also
 814              // done, for example, when deciding if "<" denotes rank ordering on datatypes.
 815              // Second, for map subtraction, it would be nice to allow the right-hand operand to be either a set or
 816              // an iset. That would also lead to further complexity in the code, so this code restricts the right-hand
 817              // operand to be a set.
 1280818              var eType = PartiallyResolveTypeForMemberSelection(expr.tok, expr.Type).AsMapType;
 1280819              if (eType != null) {
 820                // allow "map - set == map"
 0821                var expected = new SetType(true, eType.Domain);
 0822                ConstrainSubtypeRelation(expected, e.E1.Type, expr.tok, "map subtraction expects right-hand operand to h
 1280823              } else {
 1280824                ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to - ({0}) must agree w
 1280825              }
 1280826            }
 1280827            break;
 828
 750829          case BinaryExpr.Opcode.Mul: {
 750830              expr.Type = new InferredTypeProxy();
 750831              AddXConstraint(e.tok, "Mullable", expr.Type, "type of * must be of a numeric type, bitvector type, or a se
 750832              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to * ({0}) must agree with
 750833              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to * ({0}) must agree wit
 750834            }
 750835            break;
 836
 837          case BinaryExpr.Opcode.In:
 838          case BinaryExpr.Opcode.NotIn:
 1660839            var subjectDescription = e.E1.tok is QuantifiedVariableDomainToken
 1660840              ? "domain of quantified variable" : "second argument to \"" + BinaryExpr.OpcodeString(e.Op) + "\"";
 1660841            AddXConstraint(expr.tok, "Innable", e.E1.Type, e.E0.Type, subjectDescription + " must be a set, multiset, or
 1660842            expr.Type = Type.Bool;
 1660843            break;
 844
 845          case BinaryExpr.Opcode.Div:
 830846            expr.Type = new InferredTypeProxy();
 830847            AddXConstraint(expr.tok, "NumericOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 830848            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 830849              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 830850              e.E0.Type, expr.Type);
 830851            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 830852              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 830853              e.E1.Type, expr.Type);
 830854            break;
 855
 856          case BinaryExpr.Opcode.Mod:
 830857            expr.Type = new InferredTypeProxy();
 830858            AddXConstraint(expr.tok, "IntLikeOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 830859            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 830860              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 830861              e.E0.Type, expr.Type);
 830862            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 830863              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 830864              e.E1.Type, expr.Type);
 830865            break;
 866
 867          case BinaryExpr.Opcode.BitwiseAnd:
 868          case BinaryExpr.Opcode.BitwiseOr:
 869          case BinaryExpr.Opcode.BitwiseXor:
 0870            expr.Type = NewIntegerBasedProxy(expr.tok);
 0871            var errFormat = "first argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instea
 0872            ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr, errFormat, e.E0.Type);
 0873            AddXConstraint(expr.tok, "IsBitvector", e.E0.Type, errFormat);
 0874            errFormat = "second argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instead g
 0875            ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr, errFormat, e.E1.Type);
 0876            AddXConstraint(expr.tok, "IsBitvector", e.E1.Type, errFormat);
 0877            break;
 878
 879          default:
 0880            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 881        }
 882        // We should also fill in e.ResolvedOp, but we may not have enough information for that yet.  So, instead, delay
 883        // setting e.ResolvedOp until inside CheckTypeInference.
 884
 115410885      } else if (expr is TernaryExpr) {
 0886        var e = (TernaryExpr)expr;
 0887        ResolveExpression(e.E0, resolutionContext);
 0888        ResolveExpression(e.E1, resolutionContext);
 0889        ResolveExpression(e.E2, resolutionContext);
 0890        switch (e.Op) {
 891          case TernaryExpr.Opcode.PrefixEqOp:
 892          case TernaryExpr.Opcode.PrefixNeqOp:
 0893            AddXConstraint(expr.tok, "IntOrORDINAL", e.E0.Type, "prefix-equality limit argument must be an ORDINAL or in
 0894            AddXConstraint(expr.tok, "Equatable", e.E1.Type, e.E2.Type, "arguments must have the same type (got {0} and 
 0895            AddXConstraint(expr.tok, "IsCoDatatype", e.E1.Type, "arguments to prefix equality must be codatatypes (inste
 0896            expr.Type = Type.Bool;
 0897            break;
 898          default:
 0899            Contract.Assert(false);  // unexpected ternary operator
 0900            break;
 901        }
 902
 91240903      } else if (expr is LetExpr) {
 38390904        var e = (LetExpr)expr;
 76780905        if (e.Exact) {
 230340906          foreach (var rhs in e.RHSs) {
 38390907            ResolveExpression(rhs, resolutionContext);
 38390908          }
 38390909          scope.PushMarker();
 38390910          if (e.LHSs.Count != e.RHSs.Count) {
 0911            reporter.Error(MessageSource.Resolver, expr, "let expression must have same number of LHSs (found {0}) as RH
 0912          }
 38390913          var i = 0;
 230340914          foreach (var lhs in e.LHSs) {
 38390915            var rhsType = i < e.RHSs.Count ? e.RHSs[i].Type : new InferredTypeProxy();
 38390916            ResolveCasePattern(lhs, rhsType, resolutionContext);
 917            // Check for duplicate names now, because not until after resolving the case pattern do we know if identifie
 38390918            var c = 0;
 230340919            foreach (var v in lhs.Vars) {
 38390920              ScopePushAndReport(scope, v, "let-variable");
 38390921              c++;
 38390922            }
 38390923            if (c == 0) {
 924              // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constan
 0925              reporter.Error(MessageSource.Resolver, lhs.tok, "LHS is a constant literal; to be legal, it must introduce
 0926            }
 38390927            i++;
 38390928          }
 38390929        } else {
 930          // let-such-that expression
 0931          if (e.RHSs.Count != 1) {
 0932            reporter.Error(MessageSource.Resolver, expr, "let-such-that expression must have just one RHS (found {0})", 
 0933          }
 934          // the bound variables are in scope in the RHS of a let-such-that expression
 0935          scope.PushMarker();
 0936          foreach (var lhs in e.LHSs) {
 0937            Contract.Assert(lhs.Var != null);  // the parser already checked that every LHS is a BoundVar, not a general
 0938            var v = lhs.Var;
 0939            ScopePushAndReport(scope, v, "let-variable");
 0940            ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0941          }
 0942          foreach (var rhs in e.RHSs) {
 0943            ResolveExpression(rhs, resolutionContext);
 0944            ConstrainTypeExprBool(rhs, "type of RHS of let-such-that expression must be boolean (got {0})");
 0945          }
 0946        }
 38390947        ResolveExpression(e.Body, resolutionContext);
 38390948        ResolveAttributes(e, resolutionContext);
 38390949        scope.PopMarker();
 38390950        expr.Type = e.Body.Type;
 52850951      } else if (expr is LetOrFailExpr) {
 0952        var e = (LetOrFailExpr)expr;
 0953        ResolveLetOrFailExpr(e, resolutionContext);
 14460954      } else if (expr is QuantifierExpr) {
 0955        var e = (QuantifierExpr)expr;
 0956        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 0957        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0958        scope.PushMarker();
 0959        foreach (BoundVar v in e.BoundVars) {
 0960          ScopePushAndReport(scope, v, "bound-variable");
 0961          var option = new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies);
 0962          ResolveType(v.tok, v.Type, resolutionContext, option, null);
 0963        }
 0964        if (e.Range != null) {
 0965          ResolveExpression(e.Range, resolutionContext);
 0966          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0967          ConstrainTypeExprBool(e.Range, "range of quantifier must be of type bool (instead got {0})");
 0968        }
 0969        ResolveExpression(e.Term, resolutionContext);
 0970        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 0971        ConstrainTypeExprBool(e.Term, "body of quantifier must be of type bool (instead got {0})");
 972        // Since the body is more likely to infer the types of the bound variables, resolve it
 973        // first (above) and only then resolve the attributes (below).
 0974        ResolveAttributes(e, resolutionContext);
 0975        scope.PopMarker();
 0976        expr.Type = Type.Bool;
 977
 14460978      } else if (expr is SetComprehension) {
 0979        var e = (SetComprehension)expr;
 0980        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0981        scope.PushMarker();
 0982        foreach (BoundVar v in e.BoundVars) {
 0983          ScopePushAndReport(scope, v, "bound-variable");
 0984          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0985          var inferredProxy = v.Type as InferredTypeProxy;
 0986          if (inferredProxy != null) {
 0987            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 0988          }
 0989        }
 0990        ResolveExpression(e.Range, resolutionContext);
 0991        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0992        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 0993        ResolveExpression(e.Term, resolutionContext);
 0994        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 995
 0996        ResolveAttributes(e, resolutionContext);
 0997        scope.PopMarker();
 0998        expr.Type = new SetType(e.Finite, e.Term.Type);
 999
 144601000      } else if (expr is MapComprehension) {
 01001        var e = (MapComprehension)expr;
 01002        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 01003        scope.PushMarker();
 01004        Contract.Assert(e.BoundVars.Count == 1 || (1 < e.BoundVars.Count && e.TermLeft != null));
 01005        foreach (BoundVar v in e.BoundVars) {
 01006          ScopePushAndReport(scope, v, "bound-variable");
 01007          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 01008          var inferredProxy = v.Type as InferredTypeProxy;
 01009          if (inferredProxy != null) {
 01010            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 01011          }
 01012        }
 01013        ResolveExpression(e.Range, resolutionContext);
 01014        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01015        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 01016        if (e.TermLeft != null) {
 01017          ResolveExpression(e.TermLeft, resolutionContext);
 01018          Contract.Assert(e.TermLeft.Type != null);  // follows from postcondition of ResolveExpression
 01019        }
 01020        ResolveExpression(e.Term, resolutionContext);
 01021        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 1022
 01023        ResolveAttributes(e, resolutionContext);
 01024        scope.PopMarker();
 01025        expr.Type = new MapType(e.Finite, e.TermLeft != null ? e.TermLeft.Type : e.BoundVars[0].Type, e.Term.Type);
 1026
 197901027      } else if (expr is LambdaExpr) {
 53301028        var e = (LambdaExpr)expr;
 53301029        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 53301030        scope.PushMarker();
 563701031        foreach (BoundVar v in e.BoundVars) {
 134601032          ScopePushAndReport(scope, v, "bound-variable");
 134601033          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 134601034        }
 1035
 53301036        if (e.Range != null) {
 01037          ResolveExpression(e.Range, resolutionContext);
 01038          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01039          ConstrainTypeExprBool(e.Range, "Precondition must be boolean (got {0})");
 01040        }
 159901041        foreach (var read in e.Reads) {
 01042          ResolveFrameExpression(read, FrameExpressionUse.Reads, resolutionContext);
 01043        }
 53301044        ResolveExpression(e.Term, resolutionContext);
 53301045        Contract.Assert(e.Term.Type != null);
 53301046        scope.PopMarker();
 187901047        expr.Type = SelectAppropriateArrowType(e.tok, e.BoundVars.ConvertAll(v => v.Type), e.Body.Type, e.Reads.Count !=
 144601048      } else if (expr is WildcardExpr) {
 01049        expr.Type = new SetType(true, builtIns.ObjectQ());
 91301050      } else if (expr is StmtExpr) {
 01051        var e = (StmtExpr)expr;
 01052        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 1053
 01054        ResolveStatement(e.S, resolutionContext);
 01055        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 01056          var r = e.S as UpdateStmt;
 01057          if (r != null && r.ResolvedStatements.Count == 1) {
 01058            var call = r.ResolvedStatements[0] as CallStmt;
 01059            if (call.Method is TwoStateLemma && !resolutionContext.IsTwoState) {
 01060              reporter.Error(MessageSource.Resolver, call, "two-state lemmas can only be used in two-state contexts");
 01061            }
 01062          }
 01063        }
 1064
 01065        ResolveExpression(e.E, resolutionContext);
 01066        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 01067        expr.Type = e.E.Type;
 1068
 182601069      } else if (expr is ITEExpr) {
 91301070        ITEExpr e = (ITEExpr)expr;
 91301071        ResolveExpression(e.Test, resolutionContext);
 91301072        Contract.Assert(e.Test.Type != null);  // follows from postcondition of ResolveExpression
 91301073        ResolveExpression(e.Thn, resolutionContext);
 91301074        Contract.Assert(e.Thn.Type != null);  // follows from postcondition of ResolveExpression
 91301075        ResolveExpression(e.Els, resolutionContext);
 91301076        Contract.Assert(e.Els.Type != null);  // follows from postcondition of ResolveExpression
 91301077        ConstrainTypeExprBool(e.Test, "guard condition in if-then-else expression must be a boolean (instead got {0})");
 91301078        expr.Type = new InferredTypeProxy();
 91301079        ConstrainSubtypeRelation(expr.Type, e.Thn.Type, expr, "the two branches of an if-then-else expression must have 
 91301080        ConstrainSubtypeRelation(expr.Type, e.Els.Type, expr, "the two branches of an if-then-else expression must have 
 1081
 91301082      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 01083        ResolveNestedMatchExpr(nestedMatchExpr, resolutionContext);
 01084      } else {
 01085        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected expression
 1086      }
 1087
 15991801088      if (expr.Type == null) {
 1089        // some resolution error occurred
 01090        expr.Type = new InferredTypeProxy();
 01091      }
 1092
 15991801093      DominatingStatementLabels.PopMarker();
 27132251094    }
 1095
 434101096    void ResolveTypeParameters(List<TypeParameter/*!*/>/*!*/ tparams, bool emitErrors, TypeParameter.ParentType/*!*/ par
 1097      Contract.Requires(tparams != null);
 1098      Contract.Requires(parent != null);
 1099      // push non-duplicated type parameter names
 434101100      int index = 0;
 1812751101      foreach (TypeParameter tp in tparams) {
 257301102        if (emitErrors) {
 1103          // we're seeing this TypeParameter for the first time
 87151104          tp.Parent = parent;
 87151105          tp.PositionalIndex = index;
 87151106        }
 170151107        var r = allTypeParameters.Push(tp.Name, tp);
 257301108        if (emitErrors) {
 87151109          if (r == Scope<TypeParameter>.PushResult.Duplicate) {
 01110            reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tp, "Duplicate type-parameter name: {0}", tp.Na
 87151111          } else if (r == Scope<TypeParameter>.PushResult.Shadow) {
 01112            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tp.tok, "Shadowed type-parameter name: {0}", 
 01113          }
 87151114        }
 170151115      }
 434101116    }
 1117
 1002601118    private bool ConstrainSubtypeRelation(Type super, Type sub, Expression exprForToken, string msg, params object[] msg
 1119      Contract.Requires(sub != null);
 1120      Contract.Requires(super != null);
 1121      Contract.Requires(exprForToken != null);
 1122      Contract.Requires(msg != null);
 1123      Contract.Requires(msgArgs != null);
 1002601124      return ConstrainSubtypeRelation(super, sub, exprForToken.tok, msg, msgArgs);
 1002601125    }
 1126
 243001127    public void ConstrainTypeExprBool(Expression e, string msg) {
 1128      Contract.Requires(e != null);
 1129      Contract.Requires(msg != null);  // expected to have a {0} part
 243001130      ConstrainSubtypeRelation(Type.Bool, e.Type, e, msg, e.Type);
 243001131    }
 1132
 6049201133    public bool ConstrainSubtypeRelation(Type super, Type sub, IToken tok, string msg, params object[] msgArgs) {
 1134      Contract.Requires(sub != null);
 1135      Contract.Requires(super != null);
 1136      Contract.Requires(tok != null);
 1137      Contract.Requires(msg != null);
 1138      Contract.Requires(msgArgs != null);
 6049201139      return ConstrainSubtypeRelation(super, sub, new TypeConstraint.ErrorMsgWithToken(tok, msg, msgArgs));
 6049201140    }
 1141
 5045701142    private void ConstrainAssignable(NonProxyType lhs, Type rhs, TypeConstraint.ErrorMsg errMsg, out bool moreXConstrain
 1143      Contract.Requires(lhs != null);
 1144      Contract.Requires(rhs != null);
 1145      Contract.Requires(errMsg != null);
 1146
 5045701147      DetermineRootLeaf(lhs, out var isRoot, out _, out _, out _);
 10057401148      if (isRoot) {
 5011701149        ConstrainSubtypeRelation(lhs, rhs, errMsg, true, allowDecisions);
 5011701150        moreXConstraints = false;
 5045701151      } else {
 34001152        var lhsWithProxyArgs = Type.HeadWithProxyArgs(lhs);
 34001153        ConstrainSubtypeRelation(lhsWithProxyArgs, rhs, errMsg, false, allowDecisions);
 34001154        ConstrainAssignableTypeArgs(lhs, lhsWithProxyArgs.TypeArgs, lhs.TypeArgs, errMsg, out moreXConstraints);
 55301155        if (lhs.AsCollectionType == null) {
 21301156          var sameHead = Type.SameHead(lhs, rhs);
 21301157          if (!sameHead && lhs is UserDefinedType udtLhs && rhs is UserDefinedType udtRhs) {
 1158            // also allow the case where lhs is a possibly-null type and rhs is a non-null type
 01159            sameHead = udtLhs.ResolvedClass == (udtRhs.ResolvedClass as NonNullTypeDecl)?.Class;
 01160          }
 42401161          if (sameHead) {
 21101162            ConstrainAssignableTypeArgs(lhs, lhs.TypeArgs, rhs.TypeArgs, errMsg, out var more2);
 21101163            moreXConstraints = moreXConstraints || more2;
 21101164          }
 21301165        }
 34001166      }
 5045701167    }
 1168
 3701501169    private void ConstrainAssignableTypeArgs(Type typeHead, List<Type> A, List<Type> B, TypeConstraint.ErrorMsg errMsg, 
 1170      Contract.Requires(typeHead != null);
 1171      Contract.Requires(A != null);
 1172      Contract.Requires(B != null);
 1173      Contract.Requires(A.Count == B.Count);
 1174      Contract.Requires(errMsg != null);
 1175
 3701501176      var tok = errMsg.Tok;
 5719401177      if (B.Count == 0) {
 1178        // all done
 2017901179        moreXConstraints = false;
 3701501180      } else if (typeHead is MapType) {
 01181        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 0 expects {1} <: {0
 01182        AddAssignableConstraint(tok, A[0], B[0], em);
 01183        em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 1 expects {1} <: {0}", 
 01184        AddAssignableConstraint(tok, A[1], B[1], em);
 01185        moreXConstraints = true;
 2108101186      } else if (typeHead is CollectionType) {
 424501187        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter expects {1} <: {0}", A[0], B
 424501188        AddAssignableConstraint(tok, A[0], B[0], em);
 424501189        moreXConstraints = true;
 1683601190      } else {
 1259101191        var udt = (UserDefinedType)typeHead;  // note, collections, maps, and user-defined types are the only one with T
 1259101192        var cl = udt.ResolvedClass;
 1259101193        Contract.Assert(cl != null);
 1259101194        Contract.Assert(cl.TypeArgs.Count == B.Count);
 1259101195        moreXConstraints = false;
 12206101196        for (int i = 0; i < B.Count; i++) {
 3229301197          var msgFormat = "variance for type parameter" + (B.Count == 1 ? "" : " at index " + i) + " expects {0} {1} {2}
 6412201198          if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Co) {
 3182901199            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "co" + msgFormat, A[i], ":>", B[i]);
 3182901200            AddAssignableConstraint(tok, A[i], B[i], em);
 3182901201            moreXConstraints = true;
 3275701202          } else if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Contra) {
 46401203            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "contra" + msgFormat, A[i], "<:", B[i]);
 46401204            AddAssignableConstraint(tok, B[i], A[i], em);
 46401205            moreXConstraints = true;
 46401206          } else {
 01207            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "non" + msgFormat, A[i], "=", B[i]);
 01208            ConstrainSubtypeRelation_Equal(A[i], B[i], em);
 01209          }
 3229301210        }
 1259101211      }
 3701501212    }
 1213
 1214    /// <summary>
 1215    /// Adds the subtyping constraint that "a" and "b" are the same type.
 1216    /// </summary>
 3401217    private void ConstrainSubtypeRelation_Equal(Type a, Type b, TypeConstraint.ErrorMsg errMsg) {
 1218      Contract.Requires(a != null);
 1219      Contract.Requires(b != null);
 1220      Contract.Requires(errMsg != null);
 1221
 3401222      var proxy = a.Normalize() as TypeProxy;
 4401223      if (proxy != null && proxy.T == null && !Reaches(b, proxy, 1, new HashSet<TypeProxy>())) {
 1001224        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01225          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, b);
 01226        }
 1001227        proxy.T = b;
 1001228      }
 3401229      proxy = b.Normalize() as TypeProxy;
 5501230      if (proxy != null && proxy.T == null && !Reaches(a, proxy, 1, new HashSet<TypeProxy>())) {
 2101231        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01232          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, a);
 01233        }
 2101234        proxy.T = a;
 2101235      }
 1236
 3401237      ConstrainSubtypeRelation(a, b, errMsg, true);
 3401238      ConstrainSubtypeRelation(b, a, errMsg, true);
 3401239    }
 1240
 1241    /// <summary>
 1242    /// Adds the subtyping constraint that "sub" is a subtype of "super".
 1243    /// If this constraint seems feasible, returns "true".  Otherwise, prints error message (either "errMsg" or somethin
 1244    /// more specific) and returns "false".
 1245    /// Note, if in doubt, this method can return "true", because the constraints will be checked for sure at a later st
 1246    /// </summary>
 29236001247    private bool ConstrainSubtypeRelation(Type super, Type sub, TypeConstraint.ErrorMsg errMsg, bool keepConstraints = f
 1248      Contract.Requires(sub != null);
 1249      Contract.Requires(super != null);
 1250      Contract.Requires(errMsg != null);
 1251
 34041801252      if (!keepConstraints && super is InferredTypeProxy) {
 4805801253        var ip = (InferredTypeProxy)super;
 8596051254        if (ip.KeepConstraints) {
 3790251255          keepConstraints = true;
 3790251256        }
 4805801257      }
 30598401258      if (!keepConstraints && sub is InferredTypeProxy) {
 1362401259        var ip = (InferredTypeProxy)sub;
 1436501260        if (ip.KeepConstraints) {
 74101261          keepConstraints = true;
 74101262        }
 1362401263      }
 1264
 29236001265      super = super.NormalizeExpand(keepConstraints);
 29236001266      sub = sub.NormalizeExpand(keepConstraints);
 29236001267      var c = new TypeConstraint(super, sub, errMsg, keepConstraints);
 29236001268      AllTypeConstraints.Add(c);
 29236001269      return ConstrainSubtypeRelation_Aux(super, sub, c, keepConstraints, allowDecisions);
 29236001270    }
 29236001271    private bool ConstrainSubtypeRelation_Aux(Type super, Type sub, TypeConstraint c, bool keepConstraints, bool allowDe
 1272      Contract.Requires(sub != null);
 1273      Contract.Requires(!(sub is TypeProxy) || ((TypeProxy)sub).T == null);  // caller is expected to have Normalized aw
 1274      Contract.Requires(super != null);
 1275      Contract.Requires(!(super is TypeProxy) || ((TypeProxy)super).T == null);  // caller is expected to have Normalize
 1276      Contract.Requires(c != null);
 1277
 39453801278      if (object.ReferenceEquals(super, sub)) {
 10217801279        return true;
 26329601280      } else if (super is TypeProxy && sub is TypeProxy) {
 1281        // both are proxies
 7311401282        ((TypeProxy)sub).AddSupertype(c);
 7311401283        ((TypeProxy)super).AddSubtype(c);
 7311401284        return true;
 15233501285      } else if (sub is TypeProxy) {
 3526701286        var proxy = (TypeProxy)sub;
 3526701287        proxy.AddSupertype(c);
 3526701288        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 3526701289        return true;
 13042001290      } else if (super is TypeProxy) {
 4861901291        var proxy = (TypeProxy)super;
 4861901292        proxy.AddSubtype(c);
 4861901293        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 4861901294        return true;
 3318201295      } else {
 1296        // two non-proxy types
 1297        // set "headSymbolsAgree" to "false" if it's clear the head symbols couldn't be the same; "true" means they may 
 3318201298        bool headSymbolsAgree = Type.IsHeadSupertypeOf(super.NormalizeExpand(keepConstraints), sub);
 3318201299        if (!headSymbolsAgree) {
 01300          c.FlagAsError(this);
 01301          return false;
 1302        }
 1303        // TODO: inspect type parameters in order to produce some error messages sooner
 3318201304        return true;
 1305      }
 29236001306    }
 1307
 1308    /// <summary>
 1309    /// "root" says that the type is a non-artificial type (that is, not an ArtificialType) with no proper supertypes.
 1310    /// "leaf" says that the only possible proper subtypes are subset types of the type. Thus, the only
 1311    /// types that are not leaf types are traits and artificial types.
 1312    /// The "headIs" versions speak only about the head symbols, so it is possible that the given
 1313    /// type arguments would change the root/leaf status of the entire type.
 1314    /// </summary>
 10445617401315    void DetermineRootLeaf(Type t, out bool isRoot, out bool isLeaf, out bool headIsRoot, out bool headIsLeaf) {
 1316      Contract.Requires(t != null);
 1317      Contract.Ensures(!Contract.ValueAtReturn(out isRoot) || Contract.ValueAtReturn(out headIsRoot)); // isRoot ==> hea
 1318      Contract.Ensures(!Contract.ValueAtReturn(out isLeaf) || Contract.ValueAtReturn(out headIsLeaf)); // isLeaf ==> hea
 10445617401319      t = t.NormalizeExpandKeepConstraints();
 10445621551320      if (t.IsObjectQ) {
 8301321        isRoot = true; isLeaf = false;
 8301322        headIsRoot = true; headIsLeaf = false;
 10445681501323      } else if (t is ArrowType) {
 64101324        var arr = (ArrowType)t;
 128201325        headIsRoot = true; headIsLeaf = true;  // these are definitely true
 128201326        isRoot = true; isLeaf = true;  // set these to true until proven otherwise
 64101327        Contract.Assert(arr.Arity + 1 == arr.TypeArgs.Count);
 773501328        for (int i = 0; i < arr.TypeArgs.Count; i++) {
 215101329          var arg = arr.TypeArgs[i];
 215101330          DetermineRootLeaf(arg, out var r, out var l, out _, out _);
 366101331          if (i < arr.Arity) {
 302001332            isRoot &= l; isLeaf &= r;  // argument types are contravariant
 215101333          } else {
 128201334            isRoot &= r; isLeaf &= l;  // result type is covariant
 64101335          }
 215101336        }
 10621703801337      } else if (t is UserDefinedType) {
 176090551338        var udt = (UserDefinedType)t;
 176090551339        var cl = udt.ResolvedClass;
 352181101340        if (cl != null) {
 176555351341          if (cl is TypeParameter) {
 464801342            var tp = udt.AsTypeParameter;
 464801343            Contract.Assert(tp != null);
 929601344            headIsRoot = true; headIsLeaf = true;  // all type parameters are non-variant
 218433751345          } else if (cl is SubsetTypeDecl) {
 84686401346            headIsRoot = false; headIsLeaf = true;
 175625751347          } else if (cl is NewtypeDecl) {
 01348            headIsRoot = true; headIsLeaf = true;
 133282551349          } else if (cl is TraitDecl) {
 01350            headIsRoot = false; headIsLeaf = false;
 133286701351          } else if (cl is ClassDecl) {
 8301352            headIsRoot = false; headIsLeaf = true;
 133282551353          } else if (cl is AbstractTypeDecl) {
 01354            headIsRoot = true; headIsLeaf = true;
 133278401355          } else if (cl is InternalTypeSynonymDecl) {
 01356            Contract.Assert(object.ReferenceEquals(t, t.NormalizeExpand())); // should be opaque in scope
 01357            headIsRoot = true; headIsLeaf = true;
 133278401358          } else {
 133278401359            Contract.Assert(cl is DatatypeDecl);
 266556801360            headIsRoot = true; headIsLeaf = true;
 133278401361          }
 1362          // for "isRoot" and "isLeaf", also take into consideration the root/leaf status of type arguments
 352181101363          isRoot = headIsRoot; isLeaf = headIsLeaf;
 176090551364          Contract.Assert(udt.TypeArgs.Count == cl.TypeArgs.Count);
 1441595551365          for (int i = 0; i < udt.TypeArgs.Count; i++) {
 363138151366            var variance = cl.TypeArgs[i].Variance;
 726272151367            if (variance != TypeParameter.TPVariance.Non) {
 363134001368              DetermineRootLeaf(udt.TypeArgs[i], out var r, out var l, out _, out _);
 1369              // isRoot and isLeaf aren't duals, so Co and Contra require separate consideration beyond inversion.
 363134001370              switch (variance) {
 1087516001371                case TypeParameter.TPVariance.Co: { isRoot &= r; isLeaf &= l; break; }
 1372                // A invariably constructible subtype becomes a supertype, and thus the enclosing type is never a root.
 365020001373                case TypeParameter.TPVariance.Contra: { isRoot &= false; isLeaf &= r; break; }
 1374              }
 363134001375            }
 363138151376          }
 176090551377        } else {
 01378          isRoot = false; isLeaf = false;  // don't know
 01379          headIsRoot = false; headIsLeaf = false;
 01380        }
 10681560451381      } else if (t.IsBoolType || t.IsCharType || t.IsIntegerType || t.IsRealType || t.AsNewtype != null || t.IsBitVector
 472022601382        isRoot = true; isLeaf = true;
 472022601383        headIsRoot = true; headIsLeaf = true;
 10269458601384      } else if (t is ArtificialType) {
 01385        isRoot = false; isLeaf = false;
 01386        headIsRoot = false; headIsLeaf = false;
 10033447301387      } else if (t is MapType) {  // map, imap
 01388        Contract.Assert(t.TypeArgs.Count == 2);
 01389        DetermineRootLeaf(t.TypeArgs[0], out var r0, out _, out _, out _);
 01390        DetermineRootLeaf(t.TypeArgs[1], out var r1, out _, out _, out _);
 01391        isRoot = r0 & r1; isLeaf = r0 & r1;  // map types are covariant in both type arguments
 01392        headIsRoot = true; headIsLeaf = true;
 10151520801393      } else if (t is CollectionType) {  // set, iset, multiset, seq
 118073501394        Contract.Assert(t.TypeArgs.Count == 1);
 118073501395        DetermineRootLeaf(t.TypeArgs[0], out isRoot, out isLeaf, out _, out _);  // type is covariant is type argument
 236147001396        headIsRoot = true; headIsLeaf = true;
 10033447301397      } else {
 19830747601398        isRoot = false; isLeaf = false;  // don't know
 19830747601399        headIsRoot = false; headIsLeaf = false;
 9915373801400      }
 10445617401401    }
 1402
 4151403    int _recursionDepth = 0;
 9370101404    private bool AssignProxyAndHandleItsConstraints(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1405      Contract.Requires(proxy != null);
 1406      Contract.Requires(proxy.T == null);
 1407      Contract.Requires(t != null);
 1408      Contract.Requires(!(t is TypeProxy));
 1409      Contract.Requires(!(t is ArtificialType));
 9370101410      if (_recursionDepth == 20000) {
 01411        Contract.Assume(false);  // possible infinite recursion
 01412      }
 9370101413      _recursionDepth++;
 9370101414      var b = AssignProxyAndHandleItsConstraints_aux(proxy, t, keepConstraints);
 9370101415      _recursionDepth--;
 9370101416      return b;
 9370101417    }
 1418    /// <summary>
 1419    /// This method is called if "proxy" is an unassigned proxy and "t" is a type whose head symbol is known.
 1420    /// It always sets "proxy.T" to "t".
 1421    /// Then, it deals with the constraints of "proxy" as follows:
 1422    /// * If the constraint compares "t" with a non-proxy with a head comparable with that of "t",
 1423    ///   then add constraints that the type arguments satisfy the desired subtyping constraint
 1424    /// * If the constraint compares "t" with a non-proxy with a head not comparable with that of "t",
 1425    ///   then report an error
 1426    /// * If the constraint compares "t" with a proxy, then (depending on the constraint and "t") attempt
 1427    ///   to recursively set it
 1428    /// After this process, the proxy's .Supertypes and .Subtypes lists of constraints are no longer needed.
 1429    /// If anything is found to be infeasible, "false" is returned (and the propagation may be interrupted);
 1430    /// otherwise, "true" is returned.
 1431    /// </summary>
 9370101432    private bool AssignProxyAndHandleItsConstraints_aux(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1433      Contract.Requires(proxy != null);
 1434      Contract.Requires(proxy.T == null);
 1435      Contract.Requires(t != null);
 1436      Contract.Requires(!(t is TypeProxy));
 1437      Contract.Requires(!(t is ArtificialType));
 1438
 9370101439      t = keepConstraints ? t.Normalize() : t.NormalizeExpand();
 1440      // never violate the type constraint of a literal expression
 9370101441      var followedRequestedAssignment = true;
 53771001442      foreach (var su in proxy.Supertypes) {
 9947701443        if (su is IntVarietiesSupertype) {
 1045601444          var fam = TypeProxy.GetFamily(t);
 2091201445          if (fam == TypeProxy.Family.IntLike || fam == TypeProxy.Family.BitVector || fam == TypeProxy.Family.Ordinal) {
 1446            // good, let's continue with the request to equate the proxy with t
 1447            // unless...
 1045601448            if (t != t.NormalizeExpand()) {
 1449              // force the type to be a base type
 01450              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01451                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01452              }
 01453              t = t.NormalizeExpand();
 01454              followedRequestedAssignment = false;
 01455            }
 1045601456          } else {
 1457            // hijack the setting of proxy; to do that, we decide on a particular int variety now
 01458            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01459              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Int);
 01460            }
 01461            t = Type.Int;
 01462            followedRequestedAssignment = false;
 01463          }
 1045601464          break;
 7856501465        } else if (su is RealVarietiesSupertype) {
 01466          if (TypeProxy.GetFamily(t) == TypeProxy.Family.RealLike) {
 1467            // good, let's continue with the request to equate the proxy with t
 1468            // unless...
 01469            if (t != t.NormalizeExpand()) {
 1470              // force the type to be a base type
 01471              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01472                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01473              }
 01474              t = t.NormalizeExpand();
 01475              followedRequestedAssignment = false;
 01476            }
 01477          } else {
 1478            // hijack the setting of proxy; to do that, we decide on a particular real variety now
 01479            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01480              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Real)
 01481            }
 01482            t = Type.Real;
 01483            followedRequestedAssignment = false;
 01484          }
 01485          break;
 1486        }
 7856501487      }
 1488      // set proxy.T right away, so that we can freely recurse without having to worry about infinite recursion
 9370101489      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01490        Options.OutputWriter.WriteLine("DEBUG: setting proxy {0}.T := {1}", proxy, t);
 01491      }
 9370101492      proxy.T = t;
 1493
 1494      // check feasibility
 9370101495      DetermineRootLeaf(t, out var isRoot, out var isLeaf, out _, out _);
 1496      // propagate up
 55635901497      foreach (var c in proxy.SupertypeConstraints) {
 9175201498        var u = keepConstraints ? c.Super.NormalizeExpandKeepConstraints() : c.Super.NormalizeExpand();
 17077501499        if (!(u is TypeProxy)) {
 7902301500          ImposeSubtypingConstraint(u, t, c.ErrMsg);
 10174401501        } else if (isRoot) {
 1502          // If t is a root, we might as well constrain u now.  Otherwise, we'll wait until the .Subtype constraint of u
 999201503          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 999201504        }
 9175201505      }
 1506      // propagate down
 63886801507      foreach (var c in proxy.SubtypeConstraints) {
 11925501508        var u = keepConstraints ? c.Sub.NormalizeExpandKeepConstraints() : c.Sub.NormalizeExpand();
 11925501509        Contract.Assert(!TypeProxy.IsSupertypeOfLiteral(u));  // these should only appear among .Supertypes
 21622401510        if (!(u is TypeProxy)) {
 9696901511          ImposeSubtypingConstraint(t, u, c.ErrMsg);
 13821601512        } else if (isLeaf) {
 1513          // If t is a leaf (no pun intended), we might as well constrain u now.  Otherwise, we'll wait until the .Super
 1896101514          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 1896101515        }
 11925501516      }
 1517
 9370101518      return followedRequestedAssignment;
 9370101519    }
 1520
 1521    /// <summary>
 1522    /// Impose constraints that "sub" is a subtype of "super", returning "false" if this leads to an overconstrained sit
 1523    /// In most cases, "sub" being a subtype of "super" means that "sub" and "super" have the same head symbol and, ther
 1524    /// same number of type arguments. Depending on the polarities of the type parameters, the corresponding arguments
 1525    /// of "sub" and "super" must be in co-, in-, or contra-variant relationships to each other.
 1526    /// There are two ways "sub" can be a subtype of "super" without the two having the same head symbol.
 1527    /// One way is that "sub" is a subset type. In this case, the method starts by moving "sub" up toward "super".
 1528    /// The other way is that "super" is a trait (possibly
 1529    /// the trait "object").  By a current restriction in Dafny's type system, traits have no type parameters, so in thi
 1530    /// suffices to check that the head symbol of "super" is something that derives from "sub".
 1531    /// </summary>
 22242101532    private bool ImposeSubtypingConstraint(Type super, Type sub, TypeConstraint.ErrorMsg errorMsg) {
 1533      Contract.Requires(super != null && !(super is TypeProxy));
 1534      Contract.Requires(sub != null && !(sub is TypeProxy));
 1535      Contract.Requires(errorMsg != null);
 22242101536      super = super.NormalizeExpandKeepConstraints();
 22242101537      sub = sub.NormalizeExpandKeepConstraints();
 22242101538      List<int> polarities = ConstrainTypeHead_Recursive(super, ref sub);
 22242101539      if (polarities == null) {
 01540        errorMsg.FlagAsError(this);
 01541        return false;
 1542      }
 22242101543      bool keepConstraints = KeepConstraints(super, sub);
 22242101544      var p = polarities.Count;
 22242101545      Contract.Assert(p == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 22242101546      Contract.Assert(p == 0 || sub.TypeArgs.Count == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 87895701547      for (int i = 0; i < p; i++) {
 14470501548        var pol = polarities[i];
 14470501549        var tp = p == 1 ? "" : " " + i;
 14470501550        var errMsg = new TypeConstraint.ErrorMsgWithBase(errorMsg,
 14470501551          pol < 0 ? "contravariant type parameter{0} would require {1} <: {2}" :
 14470501552          pol > 0 ? "covariant type parameter{0} would require {2} <: {1}" :
 14470501553          "non-variant type parameter{0} would require {1} = {2}",
 14470501554          tp, super.TypeArgs[i], sub.TypeArgs[i]);
 28902201555        if (pol >= 0) {
 14431701556          if (!ConstrainSubtypeRelation(super.TypeArgs[i], sub.TypeArgs[i], errMsg, keepConstraints)) {
 01557            return false;
 1558          }
 14431701559        }
 14509301560        if (pol <= 0) {
 38801561          if (!ConstrainSubtypeRelation(sub.TypeArgs[i], super.TypeArgs[i], errMsg, keepConstraints)) {
 01562            return false;
 1563          }
 38801564        }
 14470501565      }
 22242101566      return true;
 22242101567    }
 1568
 1569    /// <summary>
 1570    /// This is a more liberal version of "ConstrainTypeHead" below. It is willing to move "sub"
 1571    /// upward toward its parents until it finds a head that matches "super", if any.
 1572    /// </summary>
 22246701573    private static List<int> ConstrainTypeHead_Recursive(Type super, ref Type sub) {
 1574      Contract.Requires(super != null);
 1575      Contract.Requires(sub != null);
 1576
 22246701577      super = super.NormalizeExpandKeepConstraints();
 22246701578      sub = sub.NormalizeExpandKeepConstraints();
 1579
 22246701580      var polarities = ConstrainTypeHead(super, sub);
 44488801581      if (polarities != null) {
 22242101582        return polarities;
 1583      }
 1584
 23001585      foreach (var subParentType in sub.ParentTypes()) {
 4601586        sub = subParentType;
 4601587        polarities = ConstrainTypeHead_Recursive(super, ref sub);
 9201588        if (polarities != null) {
 4601589          return polarities;
 1590        }
 01591      }
 1592
 01593      return null;
 22246701594    }
 1595
 1596    /// <summary>
 1597    /// Determines if the head of "sub" can be a subtype of "super".
 1598    /// If this is not possible, null is returned.
 1599    /// If it is possible, return a list of polarities, one for each type argument of "sub".  Polarities
 1600    /// indicate:
 1601    ///     +1  co-variant
 1602    ///      0  invariant
 1603    ///     -1  contra-variant
 1604    /// "sub" is of some type that can (in general) have type parameters.
 1605    /// See also note about Dafny's current type system in the description of method "ImposeSubtypingConstraint".
 1606    /// </summary>
 22246701607    private static List<int> ConstrainTypeHead(Type super, Type sub) {
 1608      Contract.Requires(super != null && !(super is TypeProxy));
 1609      Contract.Requires(sub != null && !(sub is TypeProxy));
 24298201610      if (super is IntVarietiesSupertype) {
 2051501611        var famSub = TypeProxy.GetFamily(sub);
 4103001612        if (famSub == TypeProxy.Family.IntLike || famSub == TypeProxy.Family.BitVector || famSub == TypeProxy.Family.Ord
 2051501613          return new List<int>();
 01614        } else {
 01615          return null;
 1616        }
 20195201617      } else if (super is RealVarietiesSupertype) {
 01618        if (TypeProxy.GetFamily(sub) == TypeProxy.Family.RealLike || super.Equals(sub)) {
 01619          return new List<int>();
 01620        } else {
 01621          return null;
 1622        }
 1623      }
 20195201624      switch (TypeProxy.GetFamily(super)) {
 1625        case TypeProxy.Family.Bool:
 1626        case TypeProxy.Family.Char:
 1627        case TypeProxy.Family.IntLike:
 1628        case TypeProxy.Family.RealLike:
 1629        case TypeProxy.Family.Ordinal:
 1630        case TypeProxy.Family.BitVector:
 21727401631          if (super.Equals(sub)) {
 10863701632            if (sub is UserDefinedType subUserDefinedType) {
 01633              return subUserDefinedType.ResolvedClass.TypeArgs.ConvertAll(tp => TypeParameter.Direction(tp.Variance));
 10863701634            } else {
 10863701635              return new List<int>();
 1636            }
 01637          } else {
 01638            return null;
 1639          }
 1640        case TypeProxy.Family.ValueType:
 1641        case TypeProxy.Family.Ref:
 1642        case TypeProxy.Family.Opaque:
 9331501643          break;  // more elaborate work below
 1644        case TypeProxy.Family.Unknown:
 01645          return null;
 1646        default:
 01647          Contract.Assert(false);  // unexpected type (the precondition of ConstrainTypeHead says "no proxies")
 01648          return null;  // please compiler
 1649      }
 10422501650      if (super is SetType) {
 1091001651        var tt = (SetType)super;
 1091001652        var uu = sub as SetType;
 1091001653        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1 } : null;
 10002001654      } else if (super is SeqType) {
 1761501655        return sub is SeqType ? new List<int> { 1 } : null;
 7486301656      } else if (super is MultiSetType) {
 1007301657        return sub is MultiSetType ? new List<int> { 1 } : null;
 5471701658      } else if (super is MapType) {
 01659        var tt = (MapType)super;
 01660        var uu = sub as MapType;
 01661        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1, 1 } : null;
 5471701662      } else if (super.IsObjectQ) {
 01663        return sub.IsRefType ? new List<int>() : null;
 5471701664      } else {
 1665        // The only remaining cases are that "super" is a (co)datatype, abstract type, or non-object trait/class.
 1666        // In each of these cases, "super" is a UserDefinedType.
 5471701667        var udfSuper = (UserDefinedType)super;
 5471701668        var clSuper = udfSuper.ResolvedClass;
 5471701669        if (clSuper == null) {
 01670          Contract.Assert(super.TypeArgs.Count == 0);
 01671          if (super.IsTypeParameter) {
 1672            // we're looking at a type parameter
 01673            return super.AsTypeParameter == sub.AsTypeParameter ? new List<int>() : null;
 01674          } else {
 01675            Contract.Assert(super.IsInternalTypeSynonym);
 01676            return super.AsInternalTypeSynonym == sub.AsInternalTypeSynonym ? new List<int>() : null;
 1677          }
 1678        }
 5471701679        var udfSub = sub as UserDefinedType;
 5471701680        var clSub = udfSub == null ? null : udfSub.ResolvedClass;
 5471701681        if (clSub == null) {
 01682          return null;
 10938801683        } else if (clSuper == clSub) {
 1684          // good
 5467101685          var polarities = new List<int>();
 5467101686          Contract.Assert(clSuper.TypeArgs.Count == udfSuper.TypeArgs.Count);
 5467101687          Contract.Assert(clSuper.TypeArgs.Count == udfSub.TypeArgs.Count);
 48233401688          foreach (var tp in clSuper.TypeArgs) {
 10610701689            var polarity = TypeParameter.Direction(tp.Variance);
 10610701690            polarities.Add(polarity);
 10610701691          }
 1692
 5467101693          return polarities;
 4601694        } else if (udfSub.IsRefType && super.IsObjectQ) {
 01695          return new List<int>();
 4601696        } else if (udfSub.IsNonNullRefType && super.IsObject) {
 01697          return new List<int>();
 4601698        } else {
 4601699          return null;
 1700        }
 1701      }
 22246701702    }
 22242101703    private static bool KeepConstraints(Type super, Type sub) {
 1704      Contract.Requires(super != null && !(super is TypeProxy));
 1705      Contract.Requires(sub != null && !(sub is TypeProxy));
 24293601706      if (super is IntVarietiesSupertype) {
 2051501707        return false;
 20190601708      } else if (super is RealVarietiesSupertype) {
 01709        return false;
 1710      }
 20190601711      switch (TypeProxy.GetFamily(super)) {
 1712        case TypeProxy.Family.Bool:
 1713        case TypeProxy.Family.Char:
 1714        case TypeProxy.Family.IntLike:
 1715        case TypeProxy.Family.RealLike:
 1716        case TypeProxy.Family.Ordinal:
 1717        case TypeProxy.Family.BitVector:
 10863701718          return false;
 1719        case TypeProxy.Family.ValueType:
 1720        case TypeProxy.Family.Ref:
 1721        case TypeProxy.Family.Opaque:
 9326901722          break;  // more elaborate work below
 1723        case TypeProxy.Family.Unknown:
 01724          return false;
 1725      }
 13186701726      if (super is SetType || super is SeqType || super is MultiSetType || super is MapType) {
 3859801727        return true;
 5473001728      } else if (super is ArrowType) {
 5901729        return false;
 5461201730      } else if (super.IsObjectQ) {
 01731        return false;
 5461201732      } else {
 1733        // super is UserDefinedType
 5461201734        return true;
 1735      }
 22242101736    }
 1737
 4151738    public List<TypeConstraint> AllTypeConstraints = new List<TypeConstraint>();
 4151739    public List<XConstraint> AllXConstraints = new List<XConstraint>();
 1740
 1741    public class XConstraint {
 1742      public readonly IToken tok;
 1743      public readonly string ConstraintName;
 1744      public readonly Type[] Types;
 1745      public readonly TypeConstraint.ErrorMsg errorMsg;
 25993401746      public XConstraint(IToken tok, string constraintName, Type[] types, TypeConstraint.ErrorMsg errMsg) {
 1747        Contract.Requires(tok != null);
 1748        Contract.Requires(constraintName != null);
 1749        Contract.Requires(types != null);
 1750        Contract.Requires(errMsg != null);
 12996701751        this.tok = tok;
 12996701752        ConstraintName = constraintName;
 12996701753        Types = types;
 12996701754        errorMsg = errMsg;
 12996701755      }
 1756
 01757      public override string ToString() {
 01758        var s = ConstraintName + ":";
 01759        foreach (var t in Types) {
 01760          s += " " + t;
 01761        }
 01762        return s;
 01763      }
 1764
 1765      /// <summary>
 1766      /// Tries to confirm the XConstraint.
 1767      /// If the XConstraint can be confirmed, or at least is plausible enough to have been converted into other type
 1768      /// constraints or more XConstraints, then "true" is returned and the out-parameters "convertedIntoOtherTypeConstr
 1769      /// and "moreXConstraints" are set to true accordingly.
 1770      /// If the XConstraint can be refuted, then an error message will be produced and "true" is returned (to indicate
 1771      /// that this XConstraint has finished serving its purpose).
 1772      /// If there's not enough information to confirm or refute the XConstraint, then "false" is returned.
 1773      /// </summary>
 6017586301774      public bool Confirm(Resolver resolver, bool fullstrength, out bool convertedIntoOtherTypeConstraints, out bool mor
 1775        Contract.Requires(resolver != null);
 6017586301776        convertedIntoOtherTypeConstraints = false;
 6017586301777        moreXConstraints = false;
 6017586301778        var t = Types[0].NormalizeExpand();
 11916502601779        if (t is TypeProxy) {
 5898916301780          switch (ConstraintName) {
 1781            case "Assignable":
 1782            case "Equatable":
 1783            case "EquatableArg":
 1784            case "Indexable":
 1785            case "Innable":
 1786            case "MultiIndexable":
 1787            case "IntOrORDINAL":
 1788              // have a go downstairs
 5523368101789              break;
 1790            default:
 375548201791              return false;  // there's not enough information to confirm or refute this XConstraint
 1792          }
 5523368101793        }
 1794        bool satisfied;
 5642038101795        switch (ConstraintName) {
 5618662701796          case "Assignable": {
 5618662701797              Contract.Assert(t == t.Normalize());  // it's already been normalized above
 5618662701798              var u = Types[1].NormalizeExpand();
 5618662701799              if (CheckTypeInferenceVisitor.IsDetermined(t) &&
 5618662701800                  (fullstrength
 5618662701801                   || !ProxyWithNoSubTypeConstraint(u, resolver)
 5618662701802                   || (u is TypeProxy
 5618662701803                       && Types[0].NormalizeExpandKeepConstraints() is var t0constrained
 5618662701804                       && (t0constrained.IsNonNullRefType || t0constrained.AsSubsetType != null)
 5623708401805                       && resolver.HasApplicableNullableRefTypeConstraint(new HashSet<TypeProxy>() { (TypeProxy)u })))) 
 1806                // This is the best case.  We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 5045701807                if (CheckTypeInferenceVisitor.IsDetermined(u) && t.IsSubtypeOf(u, false, true) && t.IsRefType) {
 1808                  // But we also allow cases where the rhs is a proper supertype of the lhs, and let the verifier
 1809                  // determine whether the rhs is provably an instance of the lhs.
 01810                  resolver.ConstrainAssignable((NonProxyType)u, (NonProxyType)t, errorMsg, out moreXConstraints, fullstr
 5045701811                } else {
 5045701812                  resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 5045701813                }
 5045701814                convertedIntoOtherTypeConstraints = true;
 5045701815                return true;
 5613617001816              } else if (u.IsTypeParameter) {
 1817                // we need the constraint base(t) :> u, which for a type parameter t can happen iff t :> u
 01818                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 01819                convertedIntoOtherTypeConstraints = true;
 01820                return true;
 5617263401821              } else if (Type.FromSameHead(t, u, out var tUp, out var uUp)) {
 3646401822                resolver.ConstrainAssignableTypeArgs(tUp, tUp.TypeArgs, uUp.TypeArgs, errorMsg, out moreXConstraints);
 3646401823                return true;
 5609970601824              } else if (fullstrength && t is NonProxyType) {
 1825                // We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 01826                resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 01827                convertedIntoOtherTypeConstraints = true;
 01828                return true;
 5609970601829              } else if (fullstrength && u is NonProxyType) {
 1830                // We're willing to change "base(t) :> u" to the stronger constraint "t :> u" for the sake of making pro
 01831                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 01832                convertedIntoOtherTypeConstraints = true;
 01833                return true;
 1834              }
 1835              // There's not enough information to say anything
 5609970601836              return false;
 1837            }
 1838          case "NumericType":
 01839            satisfied = t.IsNumericBased();
 01840            break;
 1841          case "IntegerType":
 4301842            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 4301843            break;
 1844          case "IsBitvector":
 01845            satisfied = t.IsBitVectorType;
 01846            break;
 1847          case "IsRefType":
 01848            satisfied = t.IsRefType;
 01849            break;
 1850          case "IsNullableRefType":
 8301851            satisfied = t.IsRefType && !t.IsNonNullRefType;
 8301852            break;
 1853          case "Orderable_Lt":
 221801854            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 221801855            break;
 1856          case "Orderable_Gt":
 13401857            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 13401858            break;
 01859          case "RankOrderable": {
 01860              var u = Types[1].NormalizeExpand();
 01861              if (u is TypeProxy) {
 01862                return false;  // not enough information
 1863              }
 01864              satisfied = (t.IsIndDatatype || t.IsTypeParameter) && u.IsIndDatatype;
 01865              break;
 1866            }
 1867          case "Plussable":
 131401868            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 131401869            break;
 1870          case "Minusable":
 12801871            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 12801872            break;
 1873          case "Mullable":
 7501874            satisfied = t.IsNumericBased() || t.IsBitVectorType || t is SetType || t is MultiSetType;
 7501875            break;
 1876          case "IntOrORDINAL":
 01877            if (!(t is TypeProxy)) {
 01878              if (TernaryExpr.PrefixEqUsesNat) {
 01879                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 01880              } else {
 01881                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBigOrdinalType;
 01882              }
 01883            } else if (fullstrength) {
 01884              var proxy = (TypeProxy)t;
 01885              if (TernaryExpr.PrefixEqUsesNat) {
 01886                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.Int);
 01887              } else {
 1888                // let's choose ORDINAL over int
 01889                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.BigOrdinal);
 01890              }
 01891              convertedIntoOtherTypeConstraints = true;
 01892              satisfied = true;
 01893            } else {
 01894              return false;
 1895            }
 01896            break;
 1897          case "NumericOrBitvector":
 378401898            satisfied = t.IsNumericBased() || t.IsBitVectorType;
 378401899            break;
 1900          case "NumericOrBitvectorOrCharOrORDINAL":
 8101901            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsCharType || t.IsBigOrdinalType;
 8101902            break;
 1903          case "IntLikeOrBitvector":
 8301904            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBitVectorType;
 8301905            break;
 1906          case "BooleanBits":
 3501907            satisfied = t.IsBoolType || t.IsBitVectorType;
 3501908            break;
 1909          case "Sizeable":
 89901910            satisfied = (t is SetType && ((SetType)t).Finite) || t is MultiSetType || t is SeqType || (t is MapType && (
 89901911            break;
 1912          case "Disjointable":
 13801913            satisfied = t is SetType || t is MultiSetType;
 13801914            break;
 1915          case "MultiSetConvertible":
 3201916            satisfied = (t is SetType && ((SetType)t).Finite) || t is SeqType;
 6401917            if (satisfied) {
 3201918              Type elementType = ((CollectionType)t).Arg;
 3201919              var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 3201920              var em = new TypeConstraint.ErrorMsgWithBase(errorMsg, "expecting element type {0} (got {1})", u, elementT
 3201921              resolver.ConstrainSubtypeRelation_Equal(elementType, u, em);
 3201922              convertedIntoOtherTypeConstraints = true;
 3201923            }
 3201924            break;
 1925          case "IsCoDatatype":
 01926            satisfied = t.IsCoDatatype;
 01927            break;
 1928          case "Indexable":
 22501929            if (!(t is TypeProxy)) {
 9601930              satisfied = t is SeqType || t is MultiSetType || t is MapType || (t.IsArrayType && t.AsArrayType.Dims == 1
 12901931            } else {
 1932              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1933              // that it does have the form "array<?>", since "object" would not be Indexable.
 3301934              var proxy = (TypeProxy)t;
 3301935              Type join = null;
 6601936              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 3301937                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 3301938                var tt = headWithProxyArgs.NormalizeExpand();
 3301939                satisfied = tt is SeqType || tt is MultiSetType || tt is MapType || (tt.IsArrayType && tt.AsArrayType.Di
 6601940                if (satisfied) {
 3301941                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 3301942                  convertedIntoOtherTypeConstraints = true;
 3301943                }
 3301944              } else {
 01945                return false;  // we can't determine the answer
 1946              }
 3301947            }
 12901948            break;
 1949          case "MultiIndexable":
 232401950            if (!(t is TypeProxy)) {
 116201951              satisfied = t is SeqType || (t.IsArrayType && t.AsArrayType.Dims == 1);
 116201952            } else {
 1953              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1954              // that it does have the form "array<?>", since "object" would not be Indexable.
 01955              var proxy = (TypeProxy)t;
 01956              Type join = null;
 01957              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 01958                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 01959                var tt = headWithProxyArgs.NormalizeExpand();
 01960                satisfied = tt is SeqType || (tt.IsArrayType && tt.AsArrayType.Dims == 1);
 01961                if (satisfied) {
 01962                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 01963                  convertedIntoOtherTypeConstraints = true;
 01964                }
 01965              } else {
 01966                return false;  // we can't determine the answer
 1967              }
 01968            }
 116201969            break;
 7679901970          case "Innable": {
 7679901971              var elementType = FindCollectionType(resolver.Options, t, true, new HashSet<TypeProxy>()) ?? FindCollectio
 7696501972              if (elementType != null) {
 16601973                var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 16601974                resolver.AddXConstraint(this.tok, "Equatable", elementType, u, new TypeConstraint.ErrorMsgWithBase(error
 16601975                moreXConstraints = true;
 16601976                return true;
 1977              }
 15326601978              if (t is TypeProxy) {
 7663301979                return false;  // not enough information to do anything
 1980              }
 01981              satisfied = false;
 01982              break;
 1983            }
 12601984          case "SeqUpdatable": {
 12601985              var xcWithExprs = (XConstraintWithExprs)this;
 12601986              var index = xcWithExprs.Exprs[0];
 12601987              var value = xcWithExprs.Exprs[1];
 20901988              if (t is SeqType) {
 8301989                var s = (SeqType)t;
 8301990                resolver.ConstrainToIntegerType(index, true, "sequence update requires integer- or bitvector-based index
 8301991                resolver.ConstrainSubtypeRelation(s.Arg, value.Type, value, "sequence update requires the value to have 
 12601992              } else if (t is MapType) {
 01993                var s = (MapType)t;
 01994                if (s.Finite) {
 01995                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "map update requires domain element to 
 01996                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "map update requires the value to have t
 01997                } else {
 01998                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "imap update requires domain element to
 01999                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "imap update requires the value to have 
 02000                }
 8602001              } else if (t is MultiSetType) {
 4302002                var s = (MultiSetType)t;
 4302003                resolver.ConstrainSubtypeRelation(s.Arg, index.Type, index, "multiset update requires domain element to 
 4302004                resolver.ConstrainToIntegerType(value, false, "multiset update requires integer-based numeric value (got
 4302005              } else {
 02006                satisfied = false;
 02007                break;
 2008              }
 12602009              convertedIntoOtherTypeConstraints = true;
 12602010              return true;
 2011            }
 2012          case "ContainerIndex":
 2013            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then its element/domai
 2014            Type indexType;
 353202015            if (t is SeqType || t.IsArrayType) {
 174302016              resolver.ConstrainToIntegerType(errorMsg.Tok, Types[1], true, errorMsg);
 174302017              convertedIntoOtherTypeConstraints = true;
 174302018              return true;
 4602019            } else if (t is MapType) {
 02020              indexType = ((MapType)t).Domain;
 9202021            } else if (t is MultiSetType) {
 4602022              indexType = ((MultiSetType)t).Arg;
 4602023            } else {
 2024              // some other head symbol; that's cool
 02025              return true;
 2026            }
 2027            // note, it's okay if "Types[1]" is a TypeProxy
 4602028            resolver.ConstrainSubtypeRelation(indexType, Types[1], errorMsg);  // use the same error message
 4602029            convertedIntoOtherTypeConstraints = true;
 4602030            return true;
 2031          case "ContainerResult":
 2032            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then the type of a sel
 2033            Type resultType;
 253602034            if (t is SeqType) {
 124502035              resultType = ((SeqType)t).Arg;
 129102036            } else if (t.IsArrayType) {
 02037              resultType = UserDefinedType.ArrayElementType(t);
 4602038            } else if (t is MapType) {
 02039              resultType = ((MapType)t).Range;
 9202040            } else if (t is MultiSetType) {
 4602041              resultType = resolver.builtIns.Nat();
 4602042            } else {
 2043              // some other head symbol; that's cool
 02044              return true;
 2045            }
 2046            // note, it's okay if "Types[1]" is a TypeProxy
 129102047            resolver.ConstrainSubtypeRelation(Types[1], resultType, errorMsg);
 129102048            convertedIntoOtherTypeConstraints = true;
 129102049            return true;
 10061402050          case "Equatable": {
 10061402051              t = Types[0].NormalizeExpandKeepConstraints();
 10061402052              var u = Types[1].NormalizeExpandKeepConstraints();
 10070702053              if (object.ReferenceEquals(t, u)) {
 9302054                return true;
 2055              }
 13530502056              if (t is TypeProxy && u is TypeProxy) {
 3478402057                return false;  // not enough information to do anything sensible
 13131902058              } else if (t is TypeProxy || u is TypeProxy) {
 2059                TypeProxy proxy;
 2060                Type other;
 9856202061                if (t is TypeProxy) {
 3298002062                  proxy = (TypeProxy)t;
 3298002063                  other = u;
 6558202064                } else {
 3260202065                  proxy = (TypeProxy)u;
 3260202066                  other = t;
 3260202067                }
 6570702068                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 12502069                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 12502070                  convertedIntoOtherTypeConstraints = true;
 12502071                  return true;
 6554002072                } else if (fullstrength) {
 2073                  // the following is rather aggressive
 8302074                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02075                    return false;
 8302076                  } else {
 16602077                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 8302078                      other = other.NormalizeExpand();  // shave off all constraints
 8302079                    }
 8302080                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 8302081                    convertedIntoOtherTypeConstraints = true;
 8302082                    break;
 2083                  }
 6537402084                } else {
 6537402085                  return false;  // not enough information
 2086                }
 2087              }
 2088
 15502089              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 31002090              if (satisfied) {
 15502091                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 15502092                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 75702093                for (int i = 0; i < a.TypeArgs.Count; i++) {
 14902094                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 14902095                    a.TypeArgs[i], b.TypeArgs[i],
 14902096                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 14902097                    a.IsRefType,
 14902098                    errorMsg));
 14902099                  moreXConstraints = true;
 14902100                }
 15502101              }
 15502102              break;
 2103            }
 4279702104          case "EquatableArg": {
 4279702105              t = Types[0].NormalizeExpandKeepConstraints();
 4279702106              var u = Types[1].NormalizeExpandKeepConstraints();
 4279702107              var moreExactThis = (XConstraint_EquatableArg)this;
 7078102108              if (t is TypeProxy && u is TypeProxy) {
 2798402109                return false;  // not enough information to do anything sensible
 2935102110              } else if (t is TypeProxy || u is TypeProxy) {
 2111                TypeProxy proxy;
 2112                Type other;
 2169002113                if (t is TypeProxy) {
 715202114                  proxy = (TypeProxy)t;
 715202115                  other = u;
 1453802116                } else {
 738602117                  proxy = (TypeProxy)u;
 738602118                  other = t;
 738602119                }
 1455402120                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 1602121                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 1602122                  convertedIntoOtherTypeConstraints = true;
 1602123                  return true;
 1452202124                } else if (fullstrength) {
 2125                  // the following is rather aggressive
 02126                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02127                    return false;
 02128                  } else {
 02129                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 02130                      other = other.NormalizeExpand();  // shave off all constraints
 02131                    }
 02132                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 02133                    convertedIntoOtherTypeConstraints = true;
 02134                    break;
 2135                  }
 1452202136                } else {
 1452202137                  return false;  // not enough information
 2138                }
 2139              }
 27502140              if (moreExactThis.TreatTypeParamAsWild && (t.IsTypeParameter || u.IsTypeParameter || t.IsAbstractType || u
 02141                return true;
 27502142              } else if (!moreExactThis.AllowSuperSub) {
 02143                resolver.ConstrainSubtypeRelation_Equal(t, u, errorMsg);
 02144                convertedIntoOtherTypeConstraints = true;
 02145                return true;
 2146              }
 2147
 2148              // okay if t<:u or u<:t (this makes type inference more manageable, though it is more liberal than one mig
 27502149              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 55002150              if (satisfied) {
 27502151                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 27502152                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 97602153                for (int i = 0; i < a.TypeArgs.Count; i++) {
 14202154                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 14202155                    a.TypeArgs[i], b.TypeArgs[i],
 14202156                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 14202157                    false,
 14202158                    errorMsg));
 14202159                  moreXConstraints = true;
 14202160                }
 27502161              }
 27502162              break;
 2163            }
 02164          case "Freshable": {
 02165              var collType = t.AsCollectionType;
 02166              if (collType is SetType || collType is SeqType) {
 02167                t = collType.Arg.NormalizeExpand();
 02168              }
 02169              if (t is TypeProxy) {
 02170                return false;  // there is not enough information
 2171              }
 02172              satisfied = t.IsRefType;
 02173              break;
 2174            }
 02175          case "ModifiesFrame": {
 02176              var u = Types[1].NormalizeExpand();  // eventual ref type
 02177              var collType = t is MapType ? null : t.AsCollectionType;
 02178              if (collType != null) {
 02179                t = collType.Arg.NormalizeExpand();
 02180              }
 02181              if (t is TypeProxy) {
 02182                if (collType != null) {
 2183                  // we know enough to convert into a subtyping constraint
 02184                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02185                  moreXConstraints = true;
 02186                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02187                  moreXConstraints = true;
 02188                  convertedIntoOtherTypeConstraints = true;
 02189                  return true;
 02190                } else {
 02191                  return false;  // there is not enough information
 2192                }
 2193              }
 02194              if (t.IsRefType) {
 02195                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02196                convertedIntoOtherTypeConstraints = true;
 02197                return true;
 2198              }
 02199              satisfied = false;
 02200              break;
 2201            }
 02202          case "ReadsFrame": {
 02203              var u = Types[1].NormalizeExpand();  // eventual ref type
 02204              var arrTy = t.AsArrowType;
 02205              if (arrTy != null) {
 02206                t = arrTy.Result.NormalizeExpand();
 02207              }
 02208              var collType = t is MapType ? null : t.AsCollectionType;
 02209              if (collType != null) {
 02210                t = collType.Arg.NormalizeExpand();
 02211              }
 02212              if (t is TypeProxy) {
 02213                if (collType != null) {
 2214                  // we know enough to convert into a subtyping constraint
 02215                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02216                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02217                  moreXConstraints = true;
 02218                  convertedIntoOtherTypeConstraints = true;
 02219                  return true;
 02220                } else {
 02221                  return false;  // there is not enough information
 2222                }
 2223              }
 02224              if (t.IsRefType && (arrTy == null || collType != null)) {
 02225                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02226                convertedIntoOtherTypeConstraints = true;
 02227                return true;
 2228              }
 02229              satisfied = false;
 02230              break;
 2231            }
 2232          default:
 02233            Contract.Assume(false);  // unknown XConstraint
 02234            return false;  // to please the compiler
 2235        }
 1085102236        if (!satisfied) {
 02237          errorMsg.FlagAsError(resolver);
 02238        }
 1085102239        return true;  // the XConstraint has served its purpose
 6017586302240      }
 2241
 79353302242      public bool ProxyWithNoSubTypeConstraint(Type u, Resolver resolver) {
 2243        Contract.Requires(u != null);
 2244        Contract.Requires(resolver != null);
 79353302245        var proxy = u as TypeProxy;
 154210902246        if (proxy != null) {
 74865902247          if (proxy.SubtypeConstraints.Any()) {
 8302248            return false;
 2249          }
 -1560618822250          foreach (var xc in resolver.AllXConstraints) {
 -14910890962251            if (xc.ConstraintName == "Assignable" && xc.Types[0] == proxy) {
 541702252              return false;
 2253            }
 -14911974362254          }
 74307602255          return true;
 2256        }
 4495702257        return false;
 79353302258      }
 2259
 02260      internal bool CouldBeAnything() {
 02261        return Types.All(t => t.NormalizeExpand() is TypeProxy);
 02262      }
 2263
 2264      /// <summary>
 2265      /// If "t" or any type among its transitive sub/super-types (depending on "towardsSub")
 2266      /// is a collection type, then returns the element/domain type of that collection.
 2267      /// Otherwise, returns null.
 2268      /// </summary>
 18749002269      Type FindCollectionType(DafnyOptions options, Type t, bool towardsSub, ISet<TypeProxy> visited) {
 2270        Contract.Requires(t != null);
 2271        Contract.Requires(visited != null);
 18749002272        t = t.NormalizeExpand();
 18749002273        if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02274          options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}, {1})", t, towardsSub ? "sub" : "super");
 02275        }
 18765602276        if (t is CollectionType) {
 16602277          if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02278            options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}) = {1}", t, ((CollectionType)t).Arg);
 02279          }
 16602280          return ((CollectionType)t).Arg;
 2281        }
 18732402282        var proxy = t as TypeProxy;
 20252802283        if (proxy == null || visited.Contains(proxy)) {
 1520402284          return null;
 2285        }
 17212002286        visited.Add(proxy);
 61844702287        foreach (var sub in towardsSub ? proxy.Subtypes : proxy.Supertypes) {
 3403702288          var e = FindCollectionType(options, sub, towardsSub, visited);
 3406102289          if (e != null) {
 2402290            return e;
 2291          }
 3401302292        }
 17209602293        return null;
 18749002294      }
 2295    }
 2296
 2297    public class XConstraintWithExprs : XConstraint {
 2298      public readonly Expression[] Exprs;
 2299      public XConstraintWithExprs(IToken tok, string constraintName, Type[] types, Expression[] exprs, TypeConstraint.Er
 25202300        : base(tok, constraintName, types, errMsg) {
 2301        Contract.Requires(tok != null);
 2302        Contract.Requires(constraintName != null);
 2303        Contract.Requires(types != null);
 2304        Contract.Requires(exprs != null);
 2305        Contract.Requires(errMsg != null);
 12602306        this.Exprs = exprs;
 12602307      }
 2308    }
 2309
 2310    public class XConstraint_EquatableArg : XConstraint {
 2311      public bool AllowSuperSub;
 2312      public bool TreatTypeParamAsWild;
 2313      public XConstraint_EquatableArg(IToken tok, Type a, Type b, bool allowSuperSub, bool treatTypeParamAsWild, TypeCon
 58202314        : base(tok, "EquatableArg", new Type[] { a, b }, errMsg) {
 2315        Contract.Requires(tok != null);
 2316        Contract.Requires(a != null);
 2317        Contract.Requires(b != null);
 2318        Contract.Requires(errMsg != null);
 29102319        AllowSuperSub = allowSuperSub;
 29102320        TreatTypeParamAsWild = treatTypeParamAsWild;
 29102321      }
 2322    }
 2323
 2324    /// <summary>
 2325    /// Solves or simplifies as many type constraints as possible.
 2326    /// If "allowDecisions" is "false", then no decisions, only determined inferences, are made; this mode is
 2327    /// appropriate for the partial solving that's done before a member lookup.
 2328    /// </summary>
 1121852329    public void PartiallySolveTypeConstraints(bool allowDecisions) {
 1121852330      int state = 0;
 38769702331      while (true) {
 19733952332        if (2 <= state && !allowDecisions) {
 2333          // time to say goodnight to Napoli
 349102334          return;
 19808502335        } else if (AllTypeConstraints.Count == 0 && AllXConstraints.Count == 0) {
 2336          // we're done
 772752337          return;
 2338        }
 2339
 18263002340        var anyNewConstraints = false;
 18263002341        var fullStrength = false;
 2342        // Process subtyping constraints
 18263002343        PrintTypeConstraintState(220 + 2 * state);
 18263002344        switch (state) {
 8134702345          case 0: {
 8134702346              var allTypeConstraints = AllTypeConstraints;
 8134702347              AllTypeConstraints = new List<TypeConstraint>();
 8134702348              var processed = new HashSet<TypeConstraint>();
 12197071202349              foreach (var c in allTypeConstraints) {
 4057555702350                ProcessOneSubtypingConstraintAndItsSubs(c, processed, fullStrength, ref anyNewConstraints);
 4057555702351              }
 2352
 8134702353              allTypeConstraints = new List<TypeConstraint>(AllTypeConstraints);  // copy the list
 12134655302354              foreach (var c in allTypeConstraints) {
 4036750402355                var super = c.Super.NormalizeExpand() as TypeProxy;
 4037109502356                if (AssignKnownEnd(super, true, fullStrength)) {
 359102357                  anyNewConstraints = true;
 4036750402358                } else if (super != null && fullStrength && AssignKnownEndsFullstrength(super)) {  // KRML: is this used
 02359                  anyNewConstraints = true;
 02360                }
 4036750402361              }
 8134702362            }
 8134702363            break;
 2364
 6458602365          case 1: {
 2366              // Process XConstraints
 2367              // confirm as many XConstraints as possible, setting "anyNewConstraints" to "true" if the confirmation
 2368              // of an XConstraint gives rise to new constraints to be handled in the loop above
 2369              bool generatedMoreXConstraints;
 9204502370              do {
 9204502371                generatedMoreXConstraints = false;
 9204502372                var allXConstraints = AllXConstraints;
 9204502373                AllXConstraints = new List<XConstraint>();
 18080347502374                foreach (var xc in allXConstraints) {
 6027707502375                  if (xc.Confirm(this, fullStrength, out var convertedIntoOtherTypeConstraints, out var moreXConstraints
 15516402376                    if (convertedIntoOtherTypeConstraints) {
 5386902377                      anyNewConstraints = true;
 10129502378                    } else {
 4742602379                      generatedMoreXConstraints = true;
 4742602380                    }
 11828702381                    if (moreXConstraints) {
 1699202382                      generatedMoreXConstraints = true;
 1699202383                    }
 6017578002384                  } else {
 6007448502385                    AllXConstraints.Add(xc);
 6007448502386                  }
 6017578002387                }
 18409002388              } while (generatedMoreXConstraints);
 6458602389            }
 6458602390            break;
 2391
 3230802392          case 2: {
 2081336202393              var assignables = AllXConstraints.Where(xc => xc.ConstraintName == "Assignable").ToList();
 3230802394              var postponeForNow = new HashSet<TypeProxy>();
 5193018902395              foreach (var constraint in AllTypeConstraints) {
 1727775502396                var lhs = constraint.Super.NormalizeExpandKeepConstraints() as NonProxyType;
 2196145002397                if (lhs != null) {
 2684411102398                  foreach (var ta in lhs.TypeArgs) {
 426434202399                    AddAllProxies(ta, postponeForNow);
 426434202400                  }
 468369502401                }
 1727775502402              }
 5193018902403              foreach (var constraint in AllTypeConstraints) {
 1727775502404                var lhs = constraint.Super.Normalize() as TypeProxy;
 2470500602405                if (lhs != null && !postponeForNow.Contains(lhs)) {
 -1139537712406                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 742799002407                  if (ProcessAssignable(lhs, rhss)) {
 73902408                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 73902409                  }
 742725102410                }
 1727775502411              }
 2177540502412              foreach (var assignable in assignables) {
 723611302413                var lhs = assignable.Types[0].Normalize() as TypeProxy;
 1423272202414                if (lhs != null && !postponeForNow.Contains(lhs)) {
 -3337405142415                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 702646702416                  if (ProcessAssignable(lhs, rhss)) {
 2985802417                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 2418                                               // process only one Assignable constraint in this way
 2985802419                    break;
 2420                  }
 696675102421                }
 720625502422              }
 3230802423            }
 3230802424            break;
 2425
 2426          case 3:
 236102427            anyNewConstraints = ConvertAssignableToSubtypeConstraints(null);
 236102428            break;
 2429
 155502430          case 4: {
 155502431              var allTC = AllTypeConstraints;
 155502432              AllTypeConstraints = new List<TypeConstraint>();
 155502433              var proxyProcessed = new HashSet<TypeProxy>();
 20097902434              foreach (var c in allTC) {
 6543802435                ProcessFullStrength_SubDirection(c.Super, proxyProcessed, ref anyNewConstraints);
 6543802436              }
 8640602437              foreach (var xc in AllXConstraints) {
 4623902438                if (xc.ConstraintName == "Assignable") {
 1899202439                  ProcessFullStrength_SubDirection(xc.Types[0], proxyProcessed, ref anyNewConstraints);
 1899202440                }
 2724702441              }
 308202442              if (!anyNewConstraints) {
 2443                // only do super-direction if sub-direction had no effect
 152702444                proxyProcessed = new HashSet<TypeProxy>();
 17872502445                foreach (var c in allTC) {
 5804802446                  ProcessFullStrength_SuperDirection(c.Sub, proxyProcessed, ref anyNewConstraints);
 5804802447                }
 7767002448                foreach (var xc in AllXConstraints) {
 4124002449                  if (xc.ConstraintName == "Assignable") {
 1687702450                    ProcessFullStrength_SuperDirection(xc.Types[1], proxyProcessed, ref anyNewConstraints);
 1687702451                  }
 2436302452                }
 152702453              }
 155502454              AllTypeConstraints.AddRange(allTC);
 155502455            }
 155502456            break;
 2457
 39002458          case 5: {
 2459              // Process default numeric types
 39002460              var allTypeConstraints = AllTypeConstraints;
 39002461              AllTypeConstraints = new List<TypeConstraint>();
 2869802462              foreach (var c in allTypeConstraints) {
 1149002463                if (c.Super is ArtificialType) {
 231402464                  var proxy = c.Sub.NormalizeExpand() as TypeProxy;
 458002465                  if (proxy != null) {
 226602466                    AssignProxyAndHandleItsConstraints(proxy, c.Super is IntVarietiesSupertype ? (Type)Type.Int : Type.R
 226602467                    anyNewConstraints = true;
 226602468                    continue;
 2469                  }
 4802470                }
 691002471                AllTypeConstraints.Add(c);
 691002472              }
 39002473            }
 39002474            break;
 2475
 8302476          case 6: {
 8302477              fullStrength = true;
 2478              bool generatedMoreXConstraints;
 8302479              do {
 8302480                generatedMoreXConstraints = false;
 8302481                var allXConstraints = AllXConstraints;
 8302482                AllXConstraints = new List<XConstraint>();
 74702483                foreach (var xc in allXConstraints) {
 24902484                  if ((xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") && xc.Confirm(this, full
 16602485                    if (convertedIntoOtherTypeConstraints) {
 8302486                      anyNewConstraints = true;
 8302487                    } else {
 02488                      generatedMoreXConstraints = true;
 02489                    }
 8302490                    if (moreXConstraints) {
 02491                      generatedMoreXConstraints = true;
 02492                    }
 16602493                  } else {
 8302494                    AllXConstraints.Add(xc);
 8302495                  }
 16602496                }
 16602497              } while (generatedMoreXConstraints);
 8302498            }
 8302499            break;
 2500
 02501          case 7: {
 2502              // Process default reference types
 02503              var allXConstraints = AllXConstraints;
 02504              AllXConstraints = new List<XConstraint>();
 02505              foreach (var xc in allXConstraints) {
 02506                if (xc.ConstraintName == "IsRefType" || xc.ConstraintName == "IsNullableRefType") {
 02507                  var proxy = xc.Types[0].Normalize() as TypeProxy;  // before we started processing default types, this
 02508                  if (proxy != null) {
 02509                    AssignProxyAndHandleItsConstraints(proxy, builtIns.ObjectQ());
 02510                    anyNewConstraints = true;
 02511                    continue;
 2512                  }
 02513                }
 02514                AllXConstraints.Add(xc);
 02515              }
 02516            }
 02517            break;
 2518
 02519          case 8: fullStrength = true; goto case 0;
 02520          case 9: fullStrength = true; goto case 1;
 2521
 02522          case 10: {
 2523              // Finally, collapse constraints involving only proxies, which will have the effect of trading some type e
 2524              // messages for type-underspecification messages.
 02525              var allTypeConstraints = AllTypeConstraints;
 02526              AllTypeConstraints = new List<TypeConstraint>();
 02527              foreach (var c in allTypeConstraints) {
 02528                var super = c.Super.NormalizeExpand();
 02529                var sub = c.Sub.NormalizeExpand();
 02530                if (super == sub) {
 02531                  continue;
 02532                } else if (super is TypeProxy && sub is TypeProxy) {
 02533                  var proxy = (TypeProxy)super;
 02534                  if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02535                    Options.OutputWriter.WriteLine("DEBUG: (merge in PartiallySolve) assigning proxy {0}.T := {1}", prox
 02536                  }
 02537                  proxy.T = sub;
 02538                  anyNewConstraints = true;  // signal a change in the constraints
 02539                  continue;
 2540                }
 02541                AllTypeConstraints.Add(c);
 02542              }
 02543            }
 02544            break;
 2545
 02546          case 11: {
 2547              // Last resort decisions. Sometimes get here even with some 'obvious'
 2548              // inferences. Before this case was added, the type inference returned with
 2549              // failure, so this is a conservative addition, and could be made more
 2550              // capable.
 02551              if (!allowDecisions) {
 02552                break;
 2553              }
 2554
 02555              foreach (var c in AllXConstraints) {
 02556                if (c.ConstraintName == "EquatableArg") {
 02557                  ConstrainSubtypeRelation_Equal(c.Types[0], c.Types[1], c.errorMsg);
 02558                  anyNewConstraints = true;
 02559                  AllXConstraints.Remove(c);
 02560                  break;
 2561                }
 02562              }
 02563              if (anyNewConstraints) {
 02564                break;
 2565              }
 2566
 02567              TypeConstraint.ErrorMsg oneSuperErrorMsg = null;
 02568              TypeConstraint.ErrorMsg oneSubErrorMsg = null;
 02569              var ss = new HashSet<Type>();
 02570              foreach (var c in AllTypeConstraints) {
 02571                var super = c.Super.NormalizeExpand();
 02572                var sub = c.Sub.NormalizeExpand();
 02573                if (super is TypeProxy && !ss.Contains(super)) {
 02574                  ss.Add(super);
 02575                }
 02576                if (sub is TypeProxy && !ss.Contains(sub)) {
 02577                  ss.Add(sub);
 02578                }
 02579              }
 2580
 02581              foreach (var t in ss) {
 02582                var lowers = new HashSet<Type>();
 02583                var uppers = new HashSet<Type>();
 02584                foreach (var c in AllTypeConstraints) {
 02585                  var super = c.Super.NormalizeExpand();
 02586                  var sub = c.Sub.NormalizeExpand();
 02587                  if (t.Equals(super)) {
 02588                    lowers.Add(sub);
 02589                    oneSubErrorMsg = c.ErrMsg;
 02590                  }
 02591                  if (t.Equals(sub)) {
 02592                    uppers.Add(super);
 02593                    oneSuperErrorMsg = c.ErrMsg;
 02594                  }
 02595                }
 2596
 02597                bool done = false;
 02598                foreach (var tl in lowers) {
 02599                  foreach (var tu in uppers) {
 02600                    if (tl.Equals(tu)) {
 02601                      if (!ContainsAsTypeParameter(tu, t)) {
 02602                        var errorMsg = new TypeConstraint.ErrorMsgWithBase(AllTypeConstraints[0].ErrMsg,
 02603                          "Decision: {0} is decided to be {1} because the latter is both the upper and lower bound to th
 02604                          t, tu);
 02605                        ConstrainSubtypeRelation_Equal(t, tu, errorMsg);
 2606                        // The above changes t so that it is a proxy with an assigned type
 02607                        anyNewConstraints = true;
 02608                        done = true;
 02609                        break;
 2610                      }
 02611                    }
 02612                  }
 02613                  if (done) {
 02614                    break;
 2615                  }
 02616                }
 02617              }
 02618              if (anyNewConstraints) {
 02619                break;
 2620              }
 2621
 02622              foreach (var t in ss) {
 02623                var lowers = new HashSet<Type>();
 02624                var uppers = new HashSet<Type>();
 02625                foreach (var c in AllTypeConstraints) {
 02626                  var super = c.Super.NormalizeExpand();
 02627                  var sub = c.Sub.NormalizeExpand();
 02628                  if (t.Equals(super)) {
 02629                    lowers.Add(sub);
 02630                  }
 2631
 02632                  if (t.Equals(sub)) {
 02633                    uppers.Add(super);
 02634                  }
 02635                }
 2636
 02637                if (uppers.Count == 0) {
 02638                  if (lowers.Count == 1) {
 02639                    var em = lowers.GetEnumerator();
 02640                    em.MoveNext();
 02641                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02642                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSubErrorMsg,
 02643                        "Decision: {0} is decided to be {1} because the latter is a lower bound to the proxy and there i
 02644                        t, em.Current);
 02645                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02646                      anyNewConstraints = true;
 02647                      break;
 2648                    }
 02649                  }
 02650                }
 02651                if (lowers.Count == 0) {
 02652                  if (uppers.Count == 1) {
 02653                    var em = uppers.GetEnumerator();
 02654                    em.MoveNext();
 02655                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02656                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSuperErrorMsg,
 02657                        "Decision: {0} is decided to be {1} because the latter is an upper bound to the proxy and there 
 02658                        t, em.Current);
 02659                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02660                      anyNewConstraints = true;
 02661                      break;
 2662                    }
 02663                  }
 02664                }
 02665              }
 2666
 02667              break;
 2668            }
 2669
 2670          case 12:
 2671            // we're so out of here
 02672            return;
 2673        }
 25913002674        if (anyNewConstraints) {
 7650002675          state = 0;
 18263002676        } else {
 10613002677          state++;
 10613002678        }
 18263002679      }
 1121852680    }
 2681
 166002682    TypeProxy NewIntegerBasedProxy(IToken tok) {
 2683      Contract.Requires(tok != null);
 166002684      var proxy = new InferredTypeProxy();
 166002685      ConstrainSubtypeRelation(new IntVarietiesSupertype(), proxy, tok, "integer literal used as if it had type {0}", pr
 166002686      return proxy;
 166002687    }
 2688
 02689    private bool ContainsAsTypeParameter(Type t, Type u) {
 02690      if (t.Equals(u)) {
 02691        return true;
 2692      }
 2693
 02694      if (t is UserDefinedType udt) {
 02695        foreach (var tp in udt.TypeArgs) {
 02696          if (ContainsAsTypeParameter(tp, u)) {
 02697            return true;
 2698          }
 02699        }
 02700      }
 02701      if (t is CollectionType st) {
 02702        foreach (var tp in st.TypeArgs) {
 02703          if (ContainsAsTypeParameter(tp, u)) {
 02704            return true;
 2705          }
 02706        }
 02707      }
 02708      return false;
 02709    }
 2710
 512823502711    private void AddAllProxies(Type type, HashSet<TypeProxy> proxies) {
 2712      Contract.Requires(type != null);
 2713      Contract.Requires(proxies != null);
 512823502714      var proxy = type as TypeProxy;
 774603202715      if (proxy != null) {
 261779702716        proxies.Add(proxy);
 512823502717      } else {
 1012299302718        foreach (var ta in type.TypeArgs) {
 86389302719          AddAllProxies(ta, proxies);
 86389302720        }
 251043802721      }
 512823502722    }
 2723
 2724    /// <summary>
 2725    /// Set "lhs" to the join of "rhss" and "lhs.Subtypes, if possible.
 2726    /// Returns "true' if something was done, or "false" otherwise.
 2727    /// </summary>
 1442386002728    private bool ProcessAssignable(TypeProxy lhs, List<Type> rhss) {
 2729      Contract.Requires(lhs != null && lhs.T == null);
 2730      Contract.Requires(rhss != null);
 1442386002731      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02732        Console.Write("DEBUG: ProcessAssignable: {0} with rhss:", lhs);
 02733        foreach (var rhs in rhss) {
 02734          Options.OutputWriter.Write(" {0}", rhs);
 02735        }
 02736        Options.OutputWriter.Write(" subtypes:");
 02737        foreach (var sub in lhs.SubtypesKeepConstraints) {
 02738          Options.OutputWriter.Write(" {0}", sub);
 02739        }
 02740        Options.OutputWriter.WriteLine();
 02741      }
 1442386002742      Type join = null;
 6144711502743      foreach (var rhs in rhss) {
 2551168902744        if (rhs is TypeProxy) { return false; }
 50046102745        join = join == null ? rhs : Type.Join(join, rhs, builtIns);
 50046102746      }
 3036574402747      foreach (var sub in lhs.SubtypesKeepConstraints) {
 1814254102748        if (sub is TypeProxy) { return false; }
 444202749        join = join == null ? sub : Type.Join(join, sub, builtIns);
 444202750      }
 5090502751      if (join == null) {
 1015402752        return false;
 3059702753      } else if (Reaches(join, lhs, 1, new HashSet<TypeProxy>())) {
 2754        // would cause a cycle, so don't do it
 02755        return false;
 3059702756      } else {
 3059702757        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02758          Options.OutputWriter.WriteLine("DEBUG: ProcessAssignable: assigning proxy {0}.T := {1}", lhs, join);
 02759        }
 3059702760        lhs.T = join;
 3059702761        return true;
 2762      }
 1442386002763    }
 2764
 2765    /// <summary>
 2766    /// Convert each Assignable(A, B) constraint into a subtyping constraint A :> B,
 2767    /// provided that:
 2768    ///  - B is a non-proxy, and
 2769    ///  - either "proxySpecialization" is null or some proxy in "proxySpecializations" prominently appears in A.
 2770    /// </summary>
 477502771    bool ConvertAssignableToSubtypeConstraints(ISet<TypeProxy>/*?*/ proxySpecializations) {
 477502772      var anyNewConstraints = false;
 2773      // If (the head of) the RHS of an Assignable is known, convert the XConstraint into a subtyping constraint
 477502774      var allX = AllXConstraints;
 477502775      AllXConstraints = new List<XConstraint>();
 646565402776      foreach (var xc in allX) {
 314214202777        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() is NonProxyType) {
 99169902778          var t0 = xc.Types[0].NormalizeExpand();
 99169902779          if (proxySpecializations == null
 99169902780            || proxySpecializations.Contains(t0)
 102028702781            || t0.TypeArgs.Exists(ta => proxySpecializations.Contains(ta))) {
 2858702782            ConstrainSubtypeRelation(t0, xc.Types[1], xc.errorMsg, true);
 2858702783            anyNewConstraints = true;
 2858702784            continue;
 2785          }
 96311202786        }
 212185602787        AllXConstraints.Add(xc);
 212185602788      }
 477502789      return anyNewConstraints;
 477502790    }
 2791
 241402792    bool TightenUpEquatable(ISet<TypeProxy> proxiesOfInterest) {
 2793      Contract.Requires(proxiesOfInterest != null);
 241402794      var anyNewConstraints = false;
 241402795      var allX = AllXConstraints;
 241402796      AllXConstraints = new List<XConstraint>();
 621394502797      foreach (var xc in allX) {
 207186402798        if (xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") {
 296302799          var t0 = xc.Types[0].NormalizeExpandKeepConstraints();
 296302800          var t1 = xc.Types[1].NormalizeExpandKeepConstraints();
 296502801          if (proxiesOfInterest.Contains(t0) || proxiesOfInterest.Contains(t1)) {
 202802            ConstrainSubtypeRelation_Equal(t0, t1, xc.errorMsg);
 202803            anyNewConstraints = true;
 202804            continue;
 2805          }
 296102806        }
 206889902807        AllXConstraints.Add(xc);
 206889902808      }
 241402809      return anyNewConstraints;
 241402810    }
 2811
 5641443802812    void ProcessOneSubtypingConstraintAndItsSubs(TypeConstraint c, ISet<TypeConstraint> processed, bool fullStrength, re
 2813      Contract.Requires(c != null);
 2814      Contract.Requires(processed != null);
 7223819602815      if (processed.Contains(c)) {
 1582375802816        return;  // our job has already been done, or is at least in progress
 2817      }
 4059068002818      processed.Add(c);
 2819
 4059068002820      var super = c.Super.NormalizeExpandKeepConstraints();
 4059068002821      var sub = c.Sub.NormalizeExpandKeepConstraints();
 2822      // Process all subtype types before going on
 4059068002823      var subProxy = sub as TypeProxy;
 8073810902824      if (subProxy != null) {
 16795893002825        foreach (var cc in subProxy.SubtypeConstraints) {
 1583888102826          ProcessOneSubtypingConstraintAndItsSubs(cc, processed, fullStrength, ref anyNewConstraints);
 1583888102827        }
 4014742902828      }
 2829      // the processing may have assigned some proxies, so we'll refresh super and sub
 4059068002830      super = super.NormalizeExpandKeepConstraints();
 4059068002831      sub = sub.NormalizeExpandKeepConstraints();
 2832
 4084854702833      if (super.Equals(sub)) {
 2834        // the constraint is satisfied, so just drop it
 4063710902835      } else if ((super is NonProxyType || super is ArtificialType) && sub is NonProxyType) {
 4642902836        ImposeSubtypingConstraint(super, sub, c.ErrMsg);
 4642902837        anyNewConstraints = true;
 4033373402838      } else if (AssignKnownEnd(sub as TypeProxy, true, fullStrength)) {
 92102839        anyNewConstraints = true;
 4028638402840      } else if (sub is TypeProxy && fullStrength && AssignKnownEndsFullstrength((TypeProxy)sub)) {
 02841        anyNewConstraints = true;
 4028546302842      } else {
 2843        // keep the constraint for now
 4028546302844        AllTypeConstraints.Add(c);
 4028546302845      }
 5641443802846    }
 2847
 14041902848    void ProcessFullStrength_SubDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2849      Contract.Requires(t != null);
 2850      Contract.Requires(processed != null);
 14041902851      var proxy = t.NormalizeExpand() as TypeProxy;
 25229702852      if (proxy != null) {
 18964402853        if (processed.Contains(proxy)) {
 7776602854          return;  // our job has already been done, or is at least in progress
 2855        }
 3411202856        processed.Add(proxy);
 2857
 27030302858        foreach (var u in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 5598902859          ProcessFullStrength_SubDirection(u, processed, ref anyNewConstraints);
 5598902860        }
 3411202861        proxy = proxy.NormalizeExpand() as TypeProxy;
 3415002862        if (proxy != null && AssignKnownEndsFullstrength_SubDirection(proxy)) {
 3802863          anyNewConstraints = true;
 3802864        }
 3411202865      }
 14041902866    }
 2867
 12938002868    void ProcessFullStrength_SuperDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2869      Contract.Requires(t != null);
 2870      Contract.Requires(processed != null);
 12938002871      var proxy = t.NormalizeExpand() as TypeProxy;
 22080002872      if (proxy != null) {
 14798202873        if (processed.Contains(proxy)) {
 5656202874          return;  // our job has already been done, or is at least in progress
 2875        }
 3485802876        processed.Add(proxy);
 2877
 26793902878        foreach (var u in proxy.Supertypes) {
 5445502879          ProcessFullStrength_SuperDirection(u, processed, ref anyNewConstraints);
 5445502880        }
 3485802881        proxy = proxy.NormalizeExpand() as TypeProxy;
 4416102882        if (proxy != null && AssignKnownEndsFullstrength_SuperDirection(proxy)) {
 930302883          anyNewConstraints = true;
 930302884        }
 3485802885      }
 12938002886    }
 2887
 2888    /// <summary>
 2889    /// Returns true if anything happened.
 2890    /// </summary>
 8073777402891    bool AssignKnownEnd(TypeProxy proxy, bool keepConstraints, bool fullStrength) {
 2892      Contract.Requires(proxy == null || proxy.T == null);  // caller is supposed to have called NormalizeExpand
 9755057902893      if (proxy == null) {
 2894        // nothing to do
 1681280502895        return false;
 2896      }
 2897      // ----- first, go light; also, prefer subtypes over supertypes
 6392496902898      IEnumerable<Type> subTypes = keepConstraints ? proxy.SubtypesKeepConstraints : proxy.Subtypes;
 6071735342899      foreach (var su in subTypes) {
 9949694202900        DetermineRootLeaf(su, out var isRoot, out _, out var headRoot, out _);
 9949694202901        Contract.Assert(!isRoot || headRoot);  // isRoot ==> headRoot
 9953594802902        if (isRoot) {
 3900602903          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2904            // adding a constraint here would cause a bad cycle, so we don't
 3900602905          } else {
 3900602906            AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 3900602907            return true;
 2908          }
 9947058002909        } else if (headRoot) {
 1264402910          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2911            // adding a constraint here would cause a bad cycle, so we don't
 1264402912          } else {
 1264402913            AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 1264402914            return true;
 2915          }
 02916        }
 9944529202917      }
 6387331902918      if (fullStrength) {
 02919        IEnumerable<Type> superTypes = keepConstraints ? proxy.SupertypesKeepConstraints : proxy.Supertypes;
 02920        foreach (var su in superTypes) {
 02921          DetermineRootLeaf(su, out _, out var isLeaf, out _, out var headLeaf);
 02922          Contract.Assert(!isLeaf || headLeaf);  // isLeaf ==> headLeaf
 02923          if (isLeaf) {
 02924            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2925              // adding a constraint here would cause a bad cycle, so we don't
 02926            } else {
 02927              AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 02928              return true;
 2929            }
 02930          } else if (headLeaf) {
 02931            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2932              // adding a constraint here would cause a bad cycle, so we don't
 02933            } else {
 02934              AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 02935              return true;
 2936            }
 02937          }
 02938        }
 02939      }
 6387331902940      return false;
 8073777402941    }
 2942
 02943    bool AssignKnownEndsFullstrength(TypeProxy proxy) {
 2944      Contract.Requires(proxy != null);
 2945      // ----- continue with full strength
 2946      // If the join of the subtypes exists, use it
 02947      var joins = new List<Type>();
 02948      foreach (var su in proxy.Subtypes) {
 02949        if (su is TypeProxy) {
 02950          continue;  // don't include proxies in the meet computation
 2951        }
 02952        int i = 0;
 02953        for (; i < joins.Count; i++) {
 02954          var j = Type.Join(joins[i], su, builtIns);
 02955          if (j != null) {
 02956            joins[i] = j;
 02957            break;
 2958          }
 02959        }
 02960        if (i == joins.Count) {
 2961          // we went to the end without finding a place to meet up
 02962          joins.Add(su);
 02963        }
 02964      }
 02965      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 2966        // we were able to compute a meet of all the subtyping constraints, so use it
 02967        AssignProxyAndHandleItsConstraints(proxy, joins[0]);
 02968        return true;
 2969      }
 2970      // If the meet of the supertypes exists, use it
 02971      var meets = new List<Type>();
 02972      foreach (var su in proxy.Supertypes) {
 02973        if (su is TypeProxy) {
 02974          continue;  // don't include proxies in the meet computation
 2975        }
 02976        int i = 0;
 02977        for (; i < meets.Count; i++) {
 02978          var j = Type.Meet(meets[i], su, builtIns);
 02979          if (j != null) {
 02980            meets[i] = j;
 02981            break;
 2982          }
 02983        }
 02984        if (i == meets.Count) {
 2985          // we went to the end without finding a place to meet
 02986          meets.Add(su);
 02987        }
 02988      }
 02989      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 2990        // we were able to compute a meet of all the subtyping constraints, so use it
 02991        AssignProxyAndHandleItsConstraints(proxy, meets[0]);
 02992        return true;
 2993      }
 2994
 02995      return false;
 02996    }
 2997
 3411202998    bool AssignKnownEndsFullstrength_SubDirection(TypeProxy proxy) {
 2999      Contract.Requires(proxy != null && proxy.T == null);
 3000      // If the join the subtypes exists, use it
 3411203001      var joins = new List<Type>();
 3411203002      var proxySubs = new HashSet<TypeProxy>();
 3411203003      proxySubs.Add(proxy);
 27030303004      foreach (var su in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 11192903005        if (su is TypeProxy) {
 5594003006          proxySubs.Add((TypeProxy)su);
 5598903007        } else {
 4903008          int i = 0;
 6003009          for (; i < joins.Count; i++) {
 1103010            var j = Type.Join(joins[i], su, builtIns);
 2203011            if (j != null) {
 1103012              joins[i] = j;
 1103013              break;
 3014            }
 03015          }
 8703016          if (i == joins.Count) {
 3017            // we went to the end without finding a place to join in
 3803018            joins.Add(su);
 3803019          }
 4903020        }
 5598903021      }
 3415003022      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 3023        // We were able to compute a join of all the subtyping constraints, so use it.
 3024        // Well, maybe.  If "join[0]" denotes a non-null type and "proxy" is something
 3025        // that could be assigned "null", then set "proxy" to the nullable version of "join[0]".
 3026        // Stated differently, think of an applicable "IsNullableRefType" constraint as
 3027        // being part of the join computation, essentially throwing in a "...?".
 3028        // Except: If the join is a tight bound--meaning, it is also a meet--then pick it
 3029        // after all, because that seems to give rise to less confusing error messages.
 3803030        if (joins[0].IsNonNullRefType) {
 03031          Type meet = null;
 03032          if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null && Type.SameHead(joi
 3033            // leave it
 03034          } else {
 03035            CloseOverAssignableRhss(proxySubs);
 03036            if (HasApplicableNullableRefTypeConstraint(proxySubs)) {
 03037              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 03038                Options.OutputWriter.WriteLine("DEBUG: Found join {0} for proxy {1}, but weakening it to {2}", joins[0],
 03039              }
 03040              AssignProxyAndHandleItsConstraints(proxy, joins[0].NormalizeExpand(), true);
 03041              return true;
 3042            }
 03043          }
 03044        }
 3803045        AssignProxyAndHandleItsConstraints(proxy, joins[0], true);
 3803046        return true;
 3047      }
 3407403048      return false;
 3411203049    }
 3050
 03051    private void CloseOverAssignableRhss(ISet<TypeProxy> proxySet) {
 3052      Contract.Requires(proxySet != null);
 03053      while (true) {
 03054        var moreChanges = false;
 03055        foreach (var xc in AllXConstraints) {
 03056          if (xc.ConstraintName == "Assignable") {
 03057            var source = xc.Types[0].Normalize() as TypeProxy;
 03058            var sink = xc.Types[1].Normalize() as TypeProxy;
 03059            if (source != null && sink != null && proxySet.Contains(source) && !proxySet.Contains(sink)) {
 03060              proxySet.Add(sink);
 03061              moreChanges = true;
 03062            }
 03063          }
 03064        }
 03065        if (!moreChanges) {
 03066          return;
 3067        }
 03068      }
 03069    }
 03070    private bool HasApplicableNullableRefTypeConstraint(ISet<TypeProxy> proxySet) {
 3071      Contract.Requires(proxySet != null);
 03072      var nullableProxies = new HashSet<TypeProxy>();
 03073      foreach (var xc in AllXConstraints) {
 03074        if (xc.ConstraintName == "IsNullableRefType") {
 03075          var npr = xc.Types[0].Normalize() as TypeProxy;
 03076          if (npr != null) {
 03077            nullableProxies.Add(npr);
 03078          }
 03079        }
 03080      }
 03081      return proxySet.Any(nullableProxies.Contains);
 03082    }
 8303083    private bool HasApplicableNullableRefTypeConstraint_SubDirection(TypeProxy proxy) {
 3084      Contract.Requires(proxy != null);
 8303085      var nullableProxies = new HashSet<TypeProxy>();
 49803086      foreach (var xc in AllXConstraints) {
 16603087        if (xc.ConstraintName == "IsNullableRefType") {
 8303088          var npr = xc.Types[0].Normalize() as TypeProxy;
 16603089          if (npr != null) {
 8303090            nullableProxies.Add(npr);
 8303091          }
 8303092        }
 8303093      }
 8303094      return HasApplicableNullableRefTypeConstraint_SubDirection_aux(proxy, nullableProxies, new HashSet<TypeProxy>());
 8303095    }
 8303096    private bool HasApplicableNullableRefTypeConstraint_SubDirection_aux(TypeProxy proxy, ISet<TypeProxy> nullableProxie
 3097      Contract.Requires(proxy != null);
 3098      Contract.Requires(nullableProxies != null);
 3099      Contract.Requires(visitedProxies != null);
 3100
 8303101      if (visitedProxies.Contains(proxy)) {
 03102        return false;
 3103      }
 8303104      visitedProxies.Add(proxy);
 3105
 16603106      if (nullableProxies.Contains(proxy)) {
 8303107        return true;
 3108      }
 3109
 03110      foreach (var sub in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 03111        var psub = sub as TypeProxy;
 03112        if (psub != null && HasApplicableNullableRefTypeConstraint_SubDirection_aux(psub, nullableProxies, visitedProxie
 03113          return true;
 3114        }
 03115      }
 03116      return false;
 8303117    }
 3118
 3374403119    bool AssignKnownEndsFullstrength_SuperDirection(TypeProxy proxy) {
 3120      Contract.Requires(proxy != null && proxy.T == null);
 3121      // First, compute the the join of the Assignable LHSs.  Then, compute
 3122      // the meet of that join and the supertypes.
 3374403123      var joins = new List<Type>();
 934853103124      foreach (var xc in AllXConstraints) {
 309894403125        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() == proxy) {
 1651103126          var su = xc.Types[0].Normalize();
 2815303127          if (su is TypeProxy) {
 1164203128            continue; // don't include proxies in the join computation
 3129          }
 486903130          int i = 0;
 498203131          for (; i < joins.Count; i++) {
 11303132            var j = Type.Join(joins[i], su, builtIns);
 22603133            if (j != null) {
 11303134              joins[i] = j;
 11303135              break;
 3136            }
 03137          }
 962503138          if (i == joins.Count) {
 3139            // we went to the end without finding a place to join in
 475603140            joins.Add(su);
 475603141          }
 486903142        }
 307079103143      }
 3144      // If the meet of the supertypes exists, use it
 3374403145      var meets = new List<Type>(joins);
 25412403146      foreach (var su in proxy.SupertypesKeepConstraints) {
 8152403147        if (su is TypeProxy) {
 3056003148          continue;  // don't include proxies in the meet computation
 3149        }
 2040403150        int i = 0;
 2585603151        for (; i < meets.Count; i++) {
 545203152          var j = Type.Meet(meets[i], su, builtIns);
 1090403153          if (j != null) {
 545203154            meets[i] = j;
 545203155            break;
 3156          }
 03157        }
 3535603158        if (i == meets.Count) {
 3159          // we went to the end without finding a place to meet up
 1495203160          meets.Add(su);
 1495203161        }
 2040403162      }
 4304703163      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 3164        // we were able to compute a meet of all the subtyping constraints, so use it
 930303165        AssignProxyAndHandleItsConstraints(proxy, meets[0], true);
 930303166        return true;
 3167      }
 2444103168      return false;
 3374403169    }
 3170
 3171    int _reaches_recursion;
 31103203172    private bool Reaches(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 31103203173      if (_reaches_recursion == 20) {
 03174        Contract.Assume(false);  // possible infinite recursion
 03175      }
 31103203176      _reaches_recursion++;
 31103203177      var b = Reaches_aux(t, proxy, direction, visited);
 31103203178      _reaches_recursion--;
 31103203179      return b;
 31103203180    }
 31103203181    private bool Reaches_aux(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 3182      Contract.Requires(t != null);
 3183      Contract.Requires(proxy != null);
 3184      Contract.Requires(visited != null);
 31103203185      t = t.NormalizeExpand();
 31103203186      var tproxy = t as TypeProxy;
 51324103187      if (tproxy == null) {
 20220903188        var polarities = Type.GetPolarities(t).ConvertAll(TypeParameter.Direction);
 20220903189        Contract.Assert(polarities != null);
 20220903190        Contract.Assert(polarities.Count <= t.TypeArgs.Count);
 85222503191        for (int i = 0; i < polarities.Count; i++) {
 14926903192          if (Reaches(t.TypeArgs[i], proxy, direction * polarities[i], visited)) {
 03193            return true;
 3194          }
 14926903195        }
 20220903196        return false;
 10883303197      } else if (tproxy == proxy) {
 1003198        return true;
 13794603199      } else if (visited.Contains(tproxy)) {
 2913303200        return false;
 7968003201      } else {
 7968003202        visited.Add(tproxy);
 14981403203        if (0 <= direction && tproxy.Subtypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03204          return true;
 3205        }
 7968003206        if (direction <= 0 && tproxy.Supertypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03207          return true;
 3208        }
 7968003209        return false;
 3210      }
 31103203211    }
 3212
 3213    /// <summary>
 3214    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3215    /// </summary>
 16603216    void ResolveClassMemberBodiesInitial(TopLevelDeclWithMembers cl) {
 3217      Contract.Requires(cl != null);
 3218      Contract.Requires(currentClass == null);
 3219      Contract.Requires(AllTypeConstraints.Count == 0);
 3220      Contract.Ensures(currentClass == null);
 3221      Contract.Ensures(AllTypeConstraints.Count == 0);
 3222
 16603223      currentClass = cl;
 601353224      foreach (MemberDecl member in cl.Members) {
 183853225        Contract.Assert(VisibleInScope(member));
 183853226        if (member is ConstantField { Rhs: { } } constantField) {
 03227          var resolutionContext = new ResolutionContext(constantField, false);
 03228          scope.PushMarker();
 03229          if (constantField.IsStatic || currentClass == null || !currentClass.AcceptThis) {
 03230            scope.AllowInstance = false;
 03231          }
 03232          ResolveExpression(constantField.Rhs, resolutionContext);
 03233          scope.PopMarker();
 03234          AddAssignableConstraint(constantField.tok, constantField.Type, constantField.Rhs.Type,
 03235            "type for constant '" + constantField.Name + "' is '{0}', but its initialization value type is '{1}'");
 03236          SolveAllTypeConstraints();
 03237        }
 183853238      }
 16603239      currentClass = null;
 16603240    }
 3241
 3242    /// <summary>
 3243    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3244    /// </summary>
 16603245    void ResolveClassMemberBodies(TopLevelDeclWithMembers cl) {
 3246      Contract.Requires(cl != null);
 3247      Contract.Requires(currentClass == null);
 3248      Contract.Requires(AllTypeConstraints.Count == 0);
 3249      Contract.Ensures(currentClass == null);
 3250      Contract.Ensures(AllTypeConstraints.Count == 0);
 3251
 16603252      currentClass = cl;
 601353253      foreach (MemberDecl member in cl.Members) {
 183853254        Contract.Assert(VisibleInScope(member));
 188003255        if (member is Field) {
 4153256          var resolutionContext = new ResolutionContext(new NoContext(currentClass.EnclosingModuleDefinition), false);
 4153257          scope.PushMarker();
 4153258          if (member.IsStatic) {
 03259            scope.AllowInstance = false;
 03260          }
 4153261          ResolveAttributes(member, resolutionContext, true);
 4153262          scope.PopMarker();
 3263
 313053264        } else if (member is Function function) {
 129203265          var ec = reporter.Count(ErrorLevel.Error);
 129203266          allTypeParameters.PushMarker();
 129203267          ResolveTypeParameters(function.TypeArgs, false, function);
 3268
 129203269          function.Resolve(this);
 129203270          allTypeParameters.PopMarker();
 129203271          if (function is ExtremePredicate { PrefixPredicate: { } prefixPredicate } && ec == reporter.Count(ErrorLevel.E
 03272            allTypeParameters.PushMarker();
 03273            ResolveTypeParameters(prefixPredicate.TypeArgs, false, prefixPredicate);
 03274            prefixPredicate.Resolve(this);
 03275            allTypeParameters.PopMarker();
 03276          }
 3277
 230203278        } else if (member is Method method) {
 50503279          var ec = reporter.Count(ErrorLevel.Error);
 50503280          allTypeParameters.PushMarker();
 50503281          ResolveTypeParameters(method.TypeArgs, false, method);
 50503282          method.Resolve(this);
 50503283          allTypeParameters.PopMarker();
 50503284          if (method is ExtremeLemma { PrefixLemma: { } prefixLemma } && ec == reporter.Count(ErrorLevel.Error)) {
 03285            allTypeParameters.PushMarker();
 03286            ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03287            prefixLemma.Resolve(this);
 03288            allTypeParameters.PopMarker();
 03289          }
 3290
 50503291        } else {
 03292          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 3293        }
 183853294        Contract.Assert(AllTypeConstraints.Count == 0);
 183853295      }
 16603296      currentClass = null;
 16603297    }
 3298
 3299    /// <summary>
 3300    /// Assumes type parameters have already been pushed
 3301    /// </summary>
 03302    void ResolveCtorTypes(DatatypeDecl/*!*/ dt, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies, Graph<CoDatatypeDecl/*!*/
 3303      Contract.Requires(dt != null);
 3304      Contract.Requires(dependencies != null);
 3305      Contract.Requires(coDependencies != null);
 03306      foreach (DatatypeCtor ctor in dt.Ctors) {
 3307
 03308        ctor.EnclosingDatatype = dt;
 3309
 03310        allTypeParameters.PushMarker();
 03311        ResolveCtorSignature(ctor, dt.TypeArgs);
 03312        allTypeParameters.PopMarker();
 3313
 03314        if (dt is IndDatatypeDecl) {
 3315          // The dependencies of interest among inductive datatypes are all (inductive data)types mentioned in the param
 03316          var idt = (IndDatatypeDecl)dt;
 03317          dependencies.AddVertex(idt);
 03318          foreach (Formal p in ctor.Formals) {
 03319            AddDatatypeDependencyEdge(idt, p.Type, dependencies);
 03320          }
 03321        } else {
 3322          // The dependencies of interest among codatatypes are just the top-level types of parameters.
 03323          var codt = (CoDatatypeDecl)dt;
 03324          coDependencies.AddVertex(codt);
 03325          foreach (var p in ctor.Formals) {
 03326            var co = p.Type.AsCoDatatype;
 03327            if (co != null && codt.EnclosingModuleDefinition == co.EnclosingModuleDefinition) {
 03328              coDependencies.AddEdge(codt, co);
 03329            }
 03330          }
 03331        }
 03332      }
 03333    }
 3334
 03335    void ResolveCtorSignature(DatatypeCtor ctor, List<TypeParameter> dtTypeArguments) {
 3336      Contract.Requires(ctor != null);
 3337      Contract.Requires(ctor.EnclosingDatatype != null);
 3338      Contract.Requires(dtTypeArguments != null);
 03339      foreach (Formal p in ctor.Formals) {
 03340        ResolveType(p.tok, p.Type, ctor.EnclosingDatatype, ResolveTypeOptionEnum.AllowPrefix, dtTypeArguments);
 03341      }
 03342    }
 3343
 03344    void AddDatatypeDependencyEdge(IndDatatypeDecl dt, Type tp, Graph<IndDatatypeDecl> dependencies) {
 3345      Contract.Requires(dt != null);
 3346      Contract.Requires(tp != null);
 3347      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 3348
 03349      tp = tp.NormalizeExpand();
 03350      var dependee = tp.AsIndDatatype;
 03351      if (dependee != null && dt.EnclosingModuleDefinition == dependee.EnclosingModuleDefinition) {
 03352        dependencies.AddEdge(dt, dependee);
 03353        foreach (var ta in ((UserDefinedType)tp).TypeArgs) {
 03354          AddDatatypeDependencyEdge(dt, ta, dependencies);
 03355        }
 03356      }
 03357    }
 3358
 03359    public void ResolveFrameExpressionTopLevel(FrameExpression fe, FrameExpressionUse use, ICodeContext codeContext) {
 03360      ResolveFrameExpression(fe, use, new ResolutionContext(codeContext, false));
 03361    }
 3362
 03363    void ResolveFrameExpression(FrameExpression fe, FrameExpressionUse use, ResolutionContext resolutionContext) {
 3364      Contract.Requires(fe != null);
 3365      Contract.Requires(resolutionContext != null);
 3366
 03367      ResolveExpression(fe.E, resolutionContext);
 03368      Type t = fe.E.Type;
 03369      Contract.Assert(t != null);  // follows from postcondition of ResolveExpression
 03370      var eventualRefType = new InferredTypeProxy();
 03371      if (use == FrameExpressionUse.Reads) {
 03372        AddXConstraint(fe.E.tok, "ReadsFrame", t, eventualRefType,
 03373          "a reads-clause expression must denote an object, a set/iset/multiset/seq of objects, or a function to a set/i
 03374      } else {
 03375        AddXConstraint(fe.E.tok, "ModifiesFrame", t, eventualRefType,
 03376          use == FrameExpressionUse.Modifies ?
 03377          "a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})" :
 03378          "an unchanged expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})");
 03379      }
 03380      if (fe.FieldName != null) {
 03381        var member = ResolveMember(fe.E.tok, eventualRefType, fe.FieldName, out var tentativeReceiverType);
 03382        var ctype = (UserDefinedType)tentativeReceiverType;  // correctness of cast follows from the DenotesClass test a
 03383        if (member == null) {
 3384          // error has already been reported by ResolveMember
 03385        } else if (!(member is Field)) {
 03386          reporter.Error(MessageSource.Resolver, fe.E, "member {0} in type {1} does not refer to a field", fe.FieldName,
 03387        } else if (member is ConstantField) {
 03388          reporter.Error(MessageSource.Resolver, fe.E, "expression is not allowed to refer to constant field {0}", fe.Fi
 03389        } else {
 03390          Contract.Assert(ctype != null && ctype.ResolvedClass != null);  // follows from postcondition of ResolveMember
 03391          fe.Field = (Field)member;
 03392        }
 03393      }
 03394    }
 3395
 03396    void ResolveIterator(IteratorDecl iter) {
 3397      Contract.Requires(iter != null);
 3398      Contract.Requires(currentClass == null);
 3399      Contract.Ensures(currentClass == null);
 3400
 03401      var initialErrorCount = reporter.Count(ErrorLevel.Error);
 3402
 3403      // Add in-parameters to the scope, but don't care about any duplication errors, since they have already been repor
 03404      scope.PushMarker();
 03405      scope.AllowInstance = false;  // disallow 'this' from use, which means that the special fields and methods added a
 03406      iter.Ins.ForEach(p => scope.Push(p.Name, p));
 03407      ResolveParameterDefaultValues(iter.Ins, new ResolutionContext(iter, false));
 3408
 3409      // Start resolving specification...
 3410      // we start with the decreases clause, because the _decreases<n> fields were only given type proxies before; we'll
 3411      // the types only after resolving the decreases clause (and it may be that some of resolution has already seen use
 3412      // these fields; so, with no further ado, here we go
 03413      ResolveAttributes(iter.Decreases, new ResolutionContext(iter, false));
 03414      Contract.Assert(iter.Decreases.Expressions.Count == iter.DecreasesFields.Count);
 03415      for (var i = 0; i < iter.Decreases.Expressions.Count; i++) {
 03416        var e = iter.Decreases.Expressions[i];
 03417        ResolveExpression(e, new ResolutionContext(iter, false));
 3418        // any type is fine, but associate this type with the corresponding _decreases<n> field
 03419        var d = iter.DecreasesFields[i];
 3420        // If the following type constraint does not hold, then: Bummer, there was a use--and a bad use--of the field be
 03421        ConstrainSubtypeRelation(d.Type, e.Type, e, "type of field {0} is {1}, but has been constrained elsewhere to be 
 03422      }
 03423      foreach (FrameExpression fe in iter.Reads.Expressions) {
 03424        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Reads, iter);
 03425      }
 03426      ResolveAttributes(iter.Modifies, new ResolutionContext(iter, false));
 03427      foreach (FrameExpression fe in iter.Modifies.Expressions) {
 03428        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Modifies, iter);
 03429      }
 03430      foreach (AttributedExpression e in iter.Requires) {
 03431        ResolveAttributes(e, new ResolutionContext(iter, false));
 03432        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03433        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03434        ConstrainTypeExprBool(e.E, "Precondition must be a boolean (got {0})");
 03435      }
 3436
 03437      scope.PopMarker();  // for the in-parameters
 3438
 3439      // We resolve the rest of the specification in an instance context.  So mentions of the in- or yield-parameters
 3440      // get resolved as field dereferences (with an implicit "this")
 03441      scope.PushMarker();
 03442      currentClass = iter;
 03443      Contract.Assert(scope.AllowInstance);
 3444
 03445      foreach (AttributedExpression e in iter.YieldRequires) {
 03446        ResolveAttributes(e, new ResolutionContext(iter, false));
 03447        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03448        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03449        ConstrainTypeExprBool(e.E, "Yield precondition must be a boolean (got {0})");
 03450      }
 03451      foreach (AttributedExpression e in iter.YieldEnsures) {
 03452        ResolveAttributes(e, new ResolutionContext(iter, true));
 03453        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03454        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03455        ConstrainTypeExprBool(e.E, "Yield postcondition must be a boolean (got {0})");
 03456      }
 03457      foreach (AttributedExpression e in iter.Ensures) {
 03458        ResolveAttributes(e, new ResolutionContext(iter, true));
 03459        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03460        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03461        ConstrainTypeExprBool(e.E, "Postcondition must be a boolean (got {0})");
 03462      }
 03463      SolveAllTypeConstraints();
 3464
 03465      var postSpecErrorCount = reporter.Count(ErrorLevel.Error);
 3466
 3467      // Resolve body
 03468      if (iter.Body != null) {
 03469        DominatingStatementLabels.PushMarker();
 03470        foreach (var req in iter.Requires) {
 03471          if (req.Label != null) {
 03472            if (DominatingStatementLabels.Find(req.Label.Name) != null) {
 03473              reporter.Error(MessageSource.Resolver, req.Label.Tok, "assert label shadows a dominating label");
 03474            } else {
 03475              var rr = DominatingStatementLabels.Push(req.Label.Name, req.Label);
 03476              Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expec
 03477            }
 03478          }
 03479        }
 03480        ResolveBlockStatement(iter.Body, ResolutionContext.FromCodeContext(iter));
 03481        DominatingStatementLabels.PopMarker();
 03482        SolveAllTypeConstraints();
 03483      }
 3484
 03485      currentClass = null;
 03486      scope.PopMarker();  // pop off the AllowInstance setting
 3487
 03488      if (postSpecErrorCount == initialErrorCount) {
 03489        iter.CreateIteratorMethodSpecs(this);
 03490      }
 03491    }
 3492
 3493    /// <summary>
 3494    /// Checks if lhs, which is expected to be a successfully resolved expression, denotes something
 3495    /// that can be assigned to.  In particular, this means that lhs denotes a mutable variable, field,
 3496    /// or array element.  If a violation is detected, an error is reported.
 3497    /// </summary>
 3927803498    public void CheckIsLvalue(Expression lhs, ResolutionContext resolutionContext) {
 3499      Contract.Requires(lhs != null);
 3500      Contract.Requires(resolutionContext != null);
 7855603501      if (lhs is IdentifierExpr) {
 3927803502        var ll = (IdentifierExpr)lhs;
 3927803503        if (!ll.Var.IsMutable) {
 03504          reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable");
 03505        }
 3927803506      } else if (lhs is MemberSelectExpr) {
 03507        var ll = (MemberSelectExpr)lhs;
 03508        var field = ll.Member as Field;
 03509        if (field == null || !field.IsUserMutable) {
 03510          if (resolutionContext.InFirstPhaseConstructor && field is ConstantField cf && !cf.IsStatic && cf.Rhs == null) 
 03511            if (Expression.AsThis(ll.Obj) != null) {
 3512              // it's cool; this field can be assigned to here
 03513            } else {
 03514              reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field of 'this'");
 03515            }
 03516          } else {
 03517            reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field");
 03518          }
 03519        }
 03520      } else if (lhs is SeqSelectExpr) {
 03521        var ll = (SeqSelectExpr)lhs;
 03522        ConstrainSubtypeRelation(ResolvedArrayType(ll.Seq.tok, 1, new InferredTypeProxy(), resolutionContext, true), ll.
 03523          "LHS of array assignment must denote an array element (found {0})", ll.Seq.Type);
 03524        if (!ll.SelectOne) {
 03525          reporter.Error(MessageSource.Resolver, ll.Seq, "cannot assign to a range of array elements (try the 'forall' s
 03526        }
 03527      } else if (lhs is MultiSelectExpr) {
 3528        // nothing to check; this can only denote an array element
 03529      } else {
 03530        reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable or field");
 03531      }
 3927803532    }
 3533
 385503534    public void ResolveBlockStatement(BlockStmt blockStmt, ResolutionContext resolutionContext) {
 3535      Contract.Requires(blockStmt != null);
 3536      Contract.Requires(resolutionContext != null);
 3537
 385503538      if (blockStmt is DividedBlockStmt) {
 03539        var div = (DividedBlockStmt)blockStmt;
 03540        Contract.Assert(currentMethod is Constructor);  // divided bodies occur only in class constructors
 03541        Contract.Assert(!resolutionContext.InFirstPhaseConstructor);  // divided bodies are never nested
 03542        foreach (Statement ss in div.BodyInit) {
 03543          ResolveStatementWithLabels(ss, resolutionContext with { InFirstPhaseConstructor = true });
 03544        }
 03545        foreach (Statement ss in div.BodyProper) {
 03546          ResolveStatementWithLabels(ss, resolutionContext);
 03547        }
 385503548      } else {
 14806803549        foreach (Statement ss in blockStmt.Body) {
 4550103550          ResolveStatementWithLabels(ss, resolutionContext);
 4550103551        }
 385503552      }
 385503553    }
 3554
 4550103555    public void ResolveStatementWithLabels(Statement stmt, ResolutionContext resolutionContext) {
 3556      Contract.Requires(stmt != null);
 3557      Contract.Requires(resolutionContext != null);
 3558
 4550103559      enclosingStatementLabels.PushMarker();
 3560      // push labels
 9100203561      for (var l = stmt.Labels; l != null; l = l.Next) {
 03562        var lnode = l.Data;
 03563        Contract.Assert(lnode.Name != null);  // LabelNode's with .Label==null are added only during resolution of the b
 03564        var prev = enclosingStatementLabels.Find(lnode.Name);
 03565        if (prev == stmt) {
 03566          reporter.Error(MessageSource.Resolver, lnode.Tok, "duplicate label");
 03567        } else if (prev != null) {
 03568          reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows an enclosing label");
 03569        } else {
 03570          var r = enclosingStatementLabels.Push(lnode.Name, stmt);
 03571          Contract.Assert(r == Scope<Statement>.PushResult.Success);  // since we just checked for duplicates, we expect
 03572          if (DominatingStatementLabels.Find(lnode.Name) != null) {
 03573            reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows a dominating label");
 03574          } else {
 03575            var rr = DominatingStatementLabels.Push(lnode.Name, lnode);
 03576            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 03577          }
 03578        }
 03579      }
 4550103580      ResolveStatement(stmt, resolutionContext);
 4550103581      enclosingStatementLabels.PopMarker();
 4550103582    }
 3583
 03584    void ResolveAlternatives(List<GuardedAlternative> alternatives, AlternativeLoopStmt loopToCatchBreaks, ResolutionCon
 3585      Contract.Requires(alternatives != null);
 3586      Contract.Requires(resolutionContext != null);
 3587
 3588      // first, resolve the guards
 03589      foreach (var alternative in alternatives) {
 03590        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 03591        ResolveExpression(alternative.Guard, resolutionContext);
 03592        Contract.Assert(alternative.Guard.Type != null);  // follows from postcondition of ResolveExpression
 03593        bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 03594        ConstrainTypeExprBool(alternative.Guard, "condition is expected to be of type bool, but is {0}");
 03595      }
 3596
 03597      if (loopToCatchBreaks != null) {
 03598        loopStack.Add(loopToCatchBreaks);  // push
 03599      }
 03600      foreach (var alternative in alternatives) {
 03601        scope.PushMarker();
 03602        DominatingStatementLabels.PushMarker();
 03603        if (alternative.IsBindingGuard) {
 03604          var exists = (ExistsExpr)alternative.Guard;
 03605          foreach (var v in exists.BoundVars) {
 03606            ScopePushAndReport(scope, v, "bound-variable");
 03607          }
 03608        }
 03609        ResolveAttributes(alternative, resolutionContext);
 03610        foreach (Statement ss in alternative.Body) {
 03611          ResolveStatementWithLabels(ss, resolutionContext);
 03612        }
 03613        DominatingStatementLabels.PopMarker();
 03614        scope.PopMarker();
 03615      }
 03616      if (loopToCatchBreaks != null) {
 03617        loopStack.RemoveAt(loopStack.Count - 1);  // pop
 03618      }
 03619    }
 3620
 3621    /// <summary>
 3622    /// Resolves the given call statement.
 3623    /// Assumes all LHSs have already been resolved (and checked for mutability).
 3624    /// </summary>
 117903625    void ResolveCallStmt(CallStmt s, ResolutionContext resolutionContext, Type receiverType) {
 3626      Contract.Requires(s != null);
 3627      Contract.Requires(resolutionContext != null);
 117903628      bool isInitCall = receiverType != null;
 3629
 117903630      var callee = s.Method;
 117903631      Contract.Assert(callee != null);  // follows from the invariant of CallStmt
 117903632      if (!isInitCall && callee is Constructor) {
 03633        reporter.Error(MessageSource.Resolver, s, "a constructor is allowed to be called only when an object is being al
 03634      }
 3635
 3636      // resolve left-hand sides (the right-hand sides are resolved below)
 884103637      foreach (var lhs in s.Lhs) {
 176803638        Contract.Assume(lhs.Type != null);  // a sanity check that LHSs have already been resolved
 176803639      }
 3640
 117903641      bool tryToResolve = false;
 117903642      if (callee.Outs.Count != s.Lhs.Count) {
 03643        if (isInitCall) {
 03644          reporter.Error(MessageSource.Resolver, s, "a method called as an initialization method must not have any resul
 03645        } else {
 03646          reporter.Error(MessageSource.Resolver, s, "wrong number of method result arguments (got {0}, expected {1})", s
 03647          tryToResolve = true;
 03648        }
 117903649      } else {
 117903650        if (isInitCall) {
 03651          if (callee.IsStatic) {
 03652            reporter.Error(MessageSource.Resolver, s.Tok, "a method called as an initialization method must not be 'stat
 03653          } else {
 03654            tryToResolve = true;
 03655          }
 117903656        } else if (!callee.IsStatic) {
 03657          if (!scope.AllowInstance && s.Receiver is ThisExpr) {
 3658            // The call really needs an instance, but that instance is given as 'this', which is not
 3659            // available in this context.  For more details, see comment in the resolution of a
 3660            // FunctionCallExpr.
 03661            reporter.Error(MessageSource.Resolver, s.Receiver, "'this' is not allowed in a 'static' context");
 03662          } else if (s.Receiver is StaticReceiverExpr) {
 03663            reporter.Error(MessageSource.Resolver, s.Receiver, "call to instance method requires an instance");
 03664          } else {
 03665            tryToResolve = true;
 03666          }
 117903667        } else {
 117903668          tryToResolve = true;
 117903669        }
 117903670      }
 3671
 235803672      if (tryToResolve) {
 117903673        var typeMap = s.MethodSelect.TypeArgumentSubstitutionsAtMemberDeclaration();
 3674        // resolve arguments
 117903675        ResolveActualParameters(s.Bindings, callee.Ins, s.Tok, callee, resolutionContext, typeMap,
 117903676          callee.IsStatic ? null : s.Receiver);
 3677        // type check the out-parameter arguments (in-parameters were type checked as part of ResolveActualParameters)
 766203678        for (int i = 0; i < callee.Outs.Count && i < s.Lhs.Count; i++) {
 176803679          var outFormal = callee.Outs[i];
 176803680          var it = outFormal.Type;
 176803681          Type st = it.Subst(typeMap);
 176803682          var lhs = s.Lhs[i];
 176803683          var what = GetLocationInformation(outFormal, callee.Outs.Count(), i, "method out-parameter");
 3684
 176803685          AddAssignableConstraint(
 176803686            s.Tok, lhs.Type, st,
 176803687            $"incorrect return type {what} (expected {{1}}, got {{0}})");
 176803688        }
 766203689        for (int i = 0; i < s.Lhs.Count; i++) {
 176803690          var lhs = s.Lhs[i];
 3691          // LHS must denote a mutable field.
 176803692          CheckIsLvalue(lhs.Resolved, resolutionContext);
 176803693        }
 117903694      }
 117903695      if (Contract.Exists(callee.Decreases.Expressions, e => e is WildcardExpr) && !resolutionContext.CodeContext.Allows
 03696        reporter.Error(MessageSource.Resolver, s.Tok, "a call to a possibly non-terminating method is allowed only if th
 03697      }
 117903698    }
 3699
 3700    /// <summary>
 3701    /// Resolve the actual arguments given in "bindings". Then, check that there is exactly one
 3702    /// actual for each formal, and impose assignable constraints.
 3703    /// "typeMap" is applied to the type of each formal.
 3704    /// This method should be called only once. That is, bindings.arguments is required to be null on entry to this meth
 3705    /// </summary>
 3706    void ResolveActualParameters(ActualBindings bindings, List<Formal> formals, IToken callTok, object context, Resoluti
 1796503707      Dictionary<TypeParameter, Type> typeMap, Expression/*?*/ receiver) {
 3708      Contract.Requires(bindings != null);
 3709      Contract.Requires(formals != null);
 3710      Contract.Requires(callTok != null);
 3711      Contract.Requires(context is Method || context is Function || context is DatatypeCtor || context is ArrowType);
 3712      Contract.Requires(typeMap != null);
 3713      Contract.Requires(!bindings.WasResolved);
 3714
 3715      string whatKind;
 3716      string name;
 1914403717      if (context is Method cMethod) {
 117903718        whatKind = cMethod.WhatKind;
 117903719        name = $"{whatKind} '{cMethod.Name}'";
 1870203720      } else if (context is Function cFunction) {
 73703721        whatKind = cFunction.WhatKind;
 73703722        name = $"{whatKind} '{cFunction.Name}'";
 3276003723      } else if (context is DatatypeCtor cCtor) {
 1597403724        whatKind = "datatype constructor";
 1597403725        name = $"{whatKind} '{cCtor.Name}'";
 1604903726      } else {
 7503727        var cArrowType = (ArrowType)context;
 7503728        whatKind = "function application";
 7503729        name = $"function type '{cArrowType}'";
 7503730      }
 3731
 3732      // If all arguments are passed positionally, use simple error messages that talk about the count of arguments.
 5288403733      var onlyPositionalArguments = bindings.ArgumentBindings.TrueForAll(binding => binding.FormalParameterName == null)
 1796503734      var simpleErrorReported = false;
 3593003735      if (onlyPositionalArguments) {
 5288403736        var requiredParametersCount = formals.Count(f => f.DefaultValue == null);
 1796503737        var actualsCounts = bindings.ArgumentBindings.Count;
 1796503738        var sig = "";
 14068703739        for (int i = 0; i < formals.Count; i++) {
 3491903740          sig += (", " + formals[i].Name + ": " + formals[i].Type.ToString());
 3491903741        }
 3153403742        if (formals.Count > 0) {
 1356903743          sig = ": (" + sig[2..] + ")";
 1356903744        }
 3593003745        if (requiredParametersCount <= actualsCounts && actualsCounts <= formals.Count) {
 3746          // the situation is plausible
 1796503747        } else if (requiredParametersCount == formals.Count) {
 3748          // this is the common, classical case of no default parameter values; generate a straightforward error message
 03749          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03750          simpleErrorReported = true;
 03751        } else if (actualsCounts < requiredParametersCount) {
 03752          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03753          simpleErrorReported = true;
 03754        } else {
 03755          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03756          simpleErrorReported = true;
 03757        }
 1796503758      }
 3759
 3760      // resolve given arguments and populate the "namesToActuals" map
 1796503761      var namesToActuals = new Dictionary<string, ActualBinding>();
 5288403762      formals.ForEach(f => namesToActuals.Add(f.Name, null)); // a name mapping to "null" says it hasn't been filled in 
 1796503763      var stillAcceptingPositionalArguments = true;
 1796503764      var bindingIndex = 0;
 15865203765      foreach (var binding in bindings.ArgumentBindings) {
 3491903766        var arg = binding.Actual;
 3767        // insert the actual into "namesToActuals" under an appropriate name, unless there is an error
 3491903768        if (binding.FormalParameterName != null) {
 03769          var pname = binding.FormalParameterName.val;
 03770          stillAcceptingPositionalArguments = false;
 03771          if (!namesToActuals.TryGetValue(pname, out var b)) {
 03772            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the binding named '{pname}' does not c
 03773          } else if (b == null) {
 3774            // all is good
 03775            namesToActuals[pname] = binding;
 03776          } else if (b.FormalParameterName == null) {
 03777            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the parameter named '{pname}' is alrea
 03778          } else {
 03779            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"duplicate binding for parameter name '
 03780          }
 3491903781        } else if (!stillAcceptingPositionalArguments) {
 03782          reporter.Error(MessageSource.Resolver, arg.tok, "a positional argument is not allowed to follow named argument
 6983803783        } else if (bindingIndex < formals.Count) {
 3784          // use the name of formal corresponding to this positional argument, unless the parameter is named-only
 3491903785          var formal = formals[bindingIndex];
 3491903786          var pname = formal.Name;
 3491903787          if (formal.IsNameOnly) {
 03788            reporter.Error(MessageSource.Resolver, arg.tok,
 03789              $"nameonly parameter '{pname}' must be passed using a name binding; it cannot be passed positionally");
 03790          }
 3491903791          Contract.Assert(namesToActuals[pname] == null); // we expect this, since we've only filled parameters position
 3491903792          namesToActuals[pname] = binding;
 3491903793        } else {
 3794          // too many positional arguments
 03795          if (onlyPositionalArguments) {
 3796            // error was reported before the "foreach" loop
 03797            Contract.Assert(simpleErrorReported);
 03798          } else if (formals.Count < bindingIndex) {
 3799            // error was reported on a previous iteration of this "foreach" loop
 03800          } else {
 03801            reporter.Error(MessageSource.Resolver, callTok,
 03802              $"wrong number of arguments ({name} expects {formals.Count}, got {bindings.ArgumentBindings.Count})");
 03803          }
 03804        }
 3805
 3806        // resolve argument
 3491903807        ResolveExpression(arg, resolutionContext);
 3491903808        bindingIndex++;
 3491903809      }
 3810
 1796503811      var actuals = new List<Expression>();
 1796503812      var formalIndex = 0;
 1796503813      var substMap = new Dictionary<IVariable, Expression>();
 15865203814      foreach (var formal in formals) {
 3491903815        var b = namesToActuals[formal.Name];
 6983803816        if (b != null) {
 3491903817          actuals.Add(b.Actual);
 3491903818          substMap.Add(formal, b.Actual);
 3491903819          var what = GetLocationInformation(formal,
 3491903820            bindings.ArgumentBindings.Count(), bindings.ArgumentBindings.IndexOf(b),
 3491903821            whatKind + (context is Method ? " in-parameter" : " parameter"));
 3822
 3491903823          AddAssignableConstraint(
 3491903824            callTok, formal.Type.Subst(typeMap), b.Actual.Type,
 3491903825            $"incorrect argument type {what} (expected {{0}}, found {{1}})");
 3491903826        } else if (formal.DefaultValue != null) {
 3827          // Note, in the following line, "substMap" is passed in, but it hasn't been fully filled in until the
 3828          // end of this foreach loop. Still, that's soon enough, because DefaultValueExpression won't use it
 3829          // until FillInDefaultValueExpressions at the end of Pass 1 of the Resolver.
 03830          var n = new DefaultValueExpression(callTok, formal, receiver, substMap, typeMap);
 03831          allDefaultValueExpressions.Add(n);
 03832          actuals.Add(n);
 03833          substMap.Add(formal, n);
 03834        } else {
 3835          // parameter has no value
 03836          if (onlyPositionalArguments) {
 3837            // a simple error message has already been reported
 03838            Contract.Assert(simpleErrorReported);
 03839          } else {
 03840            var formalDescription = whatKind + (context is Method ? " in-parameter" : " parameter");
 03841            var nameWithIndex = formal.HasName && formal is not ImplicitFormal ? "'" + formal.Name + "'" : "";
 03842            if (formals.Count > 1 || nameWithIndex == "") {
 03843              nameWithIndex += nameWithIndex == "" ? "" : " ";
 03844              nameWithIndex += $"at index {formalIndex}";
 03845            }
 03846            var message = $"{formalDescription} {nameWithIndex} requires an argument of type {formal.Type}";
 03847            reporter.Error(MessageSource.Resolver, callTok, message);
 03848          }
 03849        }
 3491903850        formalIndex++;
 3491903851      }
 3852
 1796503853      bindings.AcceptArgumentExpressionsAsExactParameterList(actuals);
 1796503854    }
 3855
 3668703856    private static string GetLocationInformation(Formal parameter, int bindingCount, int bindingIndex, string formalDesc
 3668703857      var displayName = parameter.HasName && parameter is not ImplicitFormal;
 3668703858      var description = "";
 7249903859      if (bindingCount > 1) {
 3581203860        description += $"at index {bindingIndex} ";
 3581203861      }
 3862
 3668703863      description += $"for {formalDescription}";
 3864
 7317603865      if (displayName) {
 3648903866        description += $" '{parameter.Name}'";
 3648903867      }
 3868
 3668703869      return description;
 3668703870    }
 3871
 3872    /// <summary>
 3873    /// To resolve "id" in expression "E . id", do:
 3874    ///  * If E denotes a module name M:
 3875    ///      0. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 3876    ///         (if two imported types have the same name, an error message is produced here)
 3877    ///      1. Static member of M._default denoting an async task type
 3878    ///    (Note that in contrast to ResolveNameSegment_Type, imported modules, etc. are ignored)
 3879    ///  * If E denotes a type:
 3880    ///      2. a. Member of that type denoting an async task type, or:
 3881    ///         b. If allowDanglingDotName:
 3882    ///            Return the type "E" and the given "expr", letting the caller try to make sense of the final dot-name.
 3883    ///
 3884    /// Note: 1 and 2a are not used now, but they will be of interest when async task types are supported.
 3885    /// </summary>
 03886    ResolveTypeReturn ResolveDotSuffix_Type(ExprDotName expr, ResolutionContext resolutionContext, bool allowDanglingDot
 3887      Contract.Requires(expr != null);
 3888      Contract.Requires(!expr.WasResolved());
 3889      Contract.Requires(expr.Lhs is NameSegment || expr.Lhs is ExprDotName);
 3890      Contract.Requires(resolutionContext != null);
 3891      Contract.Ensures(Contract.Result<ResolveTypeReturn>() == null || allowDanglingDotName);
 3892
 3893      // resolve the LHS expression
 03894      if (expr.Lhs is NameSegment) {
 03895        ResolveNameSegment_Type((NameSegment)expr.Lhs, resolutionContext, option, defaultTypeArguments);
 03896      } else {
 03897        ResolveDotSuffix_Type((ExprDotName)expr.Lhs, resolutionContext, false, option, defaultTypeArguments);
 03898      }
 3899
 03900      if (expr.OptTypeArguments != null) {
 03901        foreach (var ty in expr.OptTypeArguments) {
 03902          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 03903        }
 03904      }
 3905
 03906      Expression r = null;  // the resolved expression, if successful
 3907
 03908      var lhs = expr.Lhs.Resolved;
 03909      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 03910        var ri = (Resolver_IdentifierExpr)lhs;
 03911        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 03912        sig = GetSignature(sig);
 3913        // For 0:
 3914
 03915        if (sig.TopLevels.TryGetValue(expr.SuffixName, out var decl)) {
 3916          // ----- 0. Member of the specified module
 03917          if (decl is AmbiguousTopLevelDecl) {
 03918            var ad = (AmbiguousTopLevelDecl)decl;
 03919            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 03920          } else {
 3921            // We have found a module name or a type name.  We create a temporary expression that will never be seen by 
 3922            // or verifier, just to have a placeholder where we can recorded what we have found.
 03923            r = CreateResolver_IdentifierExpr(expr.tok, expr.SuffixName, expr.OptTypeArguments, decl);
 03924          }
 3925#if ASYNC_TASK_TYPES
 3926        } else if (sig.StaticMembers.TryGetValue(expr.SuffixName, out member)) {
 3927          // ----- 1. static member of the specified module
 3928          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 3929          if (ReallyAmbiguousThing(ref member)) {
 3930            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 3931          } else {
 3932            var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 3933            r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMetho
 3934          }
 3935#endif
 03936        } else {
 03937          reporter.Error(MessageSource.Resolver, expr.tok, "module '{0}' does not declare a type '{1}'", ri.Decl.Name, e
 03938        }
 3939
 03940      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 03941        var ri = (Resolver_IdentifierExpr)lhs;
 3942        // ----- 2. Look up name in type
 03943        var ty = new UserDefinedType(ri.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs);
 03944        if (allowDanglingDotName && ty.IsRefType) {
 03945          return new ResolveTypeReturn(ty, expr);
 3946        }
 03947        if (r == null) {
 03948          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in type '{1}' or cannot be part 
 03949        }
 03950      }
 3951
 03952      if (r == null) {
 3953        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 03954        expr.Type = new InferredTypeProxy();
 03955      } else {
 03956        expr.ResolvedExpression = r;
 03957        expr.Type = r.Type;
 03958      }
 03959      return null;
 03960    }
 3961
 1083103962    internal Resolver_IdentifierExpr CreateResolver_IdentifierExpr(IToken tok, string name, List<Type> optTypeArguments,
 3963      Contract.Requires(tok != null);
 3964      Contract.Requires(name != null);
 3965      Contract.Requires(decl != null);
 3966      Contract.Ensures(Contract.Result<Resolver_IdentifierExpr>() != null);
 3967
 2166203968      if (!moduleInfo.IsAbstract) {
 1083103969        if (decl is ModuleDecl md && md.Signature.IsAbstract) {
 03970          reporter.Error(MessageSource.Resolver, tok, "a compiled module is not allowed to use an abstract module ({0})"
 03971        }
 1083103972      }
 1083103973      var n = optTypeArguments == null ? 0 : optTypeArguments.Count;
 1344353974      if (optTypeArguments != null) {
 3975        // type arguments were supplied; they must be equal in number to those expected
 261253976        if (n != decl.TypeArgs.Count) {
 03977          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}
 03978        }
 261253979      }
 1083103980      List<Type> tpArgs = new List<Type>();
 4123553981      for (int i = 0; i < decl.TypeArgs.Count; i++) {
 652453982        tpArgs.Add(i < n ? optTypeArguments[i] : new InferredTypeProxy());
 652453983      }
 1083103984      return new Resolver_IdentifierExpr(tok, decl, tpArgs);
 1083103985    }
 3986
 8478003987    public void ResolveStatement(Statement stmt, ResolutionContext resolutionContext) {
 3988      Contract.Requires(stmt != null);
 3989      Contract.Requires(resolutionContext != null);
 8946403990      if (stmt is ICanResolve canResolve) {
 468403991        canResolve.Resolve(this, resolutionContext);
 468403992        return;
 3993      }
 16019203994      if (!(stmt is ForallStmt || stmt is ForLoopStmt)) {  // "forall" and "for" statements do their own attribute resol
 8009603995        ResolveAttributes(stmt, resolutionContext);
 8009603996      }
 8009603997      if (stmt is PredicateStmt) {
 03998        PredicateStmt s = (PredicateStmt)stmt;
 03999        var assertStmt = stmt as AssertStmt;
 04000        if (assertStmt != null && assertStmt.Label != null) {
 04001          if (DominatingStatementLabels.Find(assertStmt.Label.Name) != null) {
 04002            reporter.Error(MessageSource.Resolver, assertStmt.Label.Tok, "assert label shadows a dominating label");
 04003          } else {
 04004            var rr = DominatingStatementLabels.Push(assertStmt.Label.Name, assertStmt.Label);
 04005            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 04006          }
 04007        }
 4008
 04009        if (assertStmt != null && Attributes.Find(assertStmt.Attributes, "only") is UserSuppliedAttributes attribute) {
 04010          reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_assumes_others.ToString(), att
 04011            "Assertion with {:only} temporarily transforms other assertions into assumptions");
 04012          if (attribute.Args.Count >= 1
 04013              && attribute.Args[0] is LiteralExpr { Value: string value }
 04014              && value != "before" && value != "after") {
 04015            reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_before_after.ToString(), att
 04016              "{:only} only accepts \"before\" or \"after\" as an optional argument");
 04017          }
 04018        }
 04019        ResolveExpression(s.Expr, resolutionContext);
 04020        Contract.Assert(s.Expr.Type != null);  // follows from postcondition of ResolveExpression
 04021        ConstrainTypeExprBool(s.Expr, "condition is expected to be of type bool, but is {0}");
 04022        if (assertStmt != null && assertStmt.Proof != null) {
 4023          // clear the labels for the duration of checking the proof body, because break statements are not allowed to l
 04024          var prevLblStmts = enclosingStatementLabels;
 04025          var prevLoopStack = loopStack;
 04026          enclosingStatementLabels = new Scope<Statement>(Options);
 04027          loopStack = new List<Statement>();
 04028          ResolveStatement(assertStmt.Proof, resolutionContext);
 04029          enclosingStatementLabels = prevLblStmts;
 04030          loopStack = prevLoopStack;
 04031        }
 04032        var expectStmt = stmt as ExpectStmt;
 04033        if (expectStmt != null) {
 04034          if (expectStmt.Message == null) {
 04035            expectStmt.Message = new StringLiteralExpr(s.Tok, "expectation violation", false);
 04036          }
 04037          ResolveExpression(expectStmt.Message, resolutionContext);
 04038          Contract.Assert(expectStmt.Message.Type != null);  // follows from postcondition of ResolveExpression
 04039        }
 4040
 8414804041      } else if (stmt is PrintStmt) {
 405204042        var s = (PrintStmt)stmt;
 1419804043        s.Args.Iter(e => ResolveExpression(e, resolutionContext));
 4044
 8009604045      } else if (stmt is RevealStmt) {
 04046        var s = (RevealStmt)stmt;
 04047        foreach (var expr in s.Exprs) {
 04048          var name = RevealStmt.SingleName(expr);
 04049          var labeledAssert = name == null ? null : DominatingStatementLabels.Find(name) as AssertLabel;
 04050          if (labeledAssert != null) {
 04051            s.LabeledAsserts.Add(labeledAssert);
 04052          } else {
 04053            var revealResolutionContext = resolutionContext with { InReveal = true };
 04054            if (expr is ApplySuffix) {
 04055              var e = (ApplySuffix)expr;
 04056              var methodCallInfo = ResolveApplySuffix(e, revealResolutionContext, true);
 04057              if (methodCallInfo == null) {
 04058                reporter.Error(MessageSource.Resolver, expr.tok, "expression has no reveal lemma");
 04059              } else if (methodCallInfo.Callee.Member is TwoStateLemma && !revealResolutionContext.IsTwoState) {
 04060                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "a two-state function can only be revealed in
 04061              } else if (methodCallInfo.Callee.AtLabel != null) {
 04062                Contract.Assert(methodCallInfo.Callee.Member is TwoStateLemma);
 04063                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "to reveal a two-state function, do not list 
 04064              } else {
 04065                var call = new CallStmt(s.RangeToken, new List<Expression>(), methodCallInfo.Callee, methodCallInfo.Actu
 04066                s.ResolvedStatements.Add(call);
 04067              }
 04068            } else if (expr is NameSegment or ExprDotName) {
 04069              if (expr is NameSegment) {
 04070                ResolveNameSegment((NameSegment)expr, true, null, revealResolutionContext, true);
 04071              } else {
 04072                ResolveDotSuffix((ExprDotName)expr, true, null, revealResolutionContext, true);
 04073              }
 04074              MemberSelectExpr callee = (MemberSelectExpr)((ConcreteSyntaxExpression)expr).ResolvedExpression;
 04075              if (callee == null) {
 04076              } else if (callee.Member is Lemma or TwoStateLemma && Attributes.Contains(callee.Member.Attributes, "axiom
 4077                //The revealed member is a function
 04078                reporter.Error(MessageSource.Resolver, callee.tok, "to reveal a function ({0}), append parentheses", cal
 04079              } else {
 04080                var call = new CallStmt(s.RangeToken, new List<Expression>(), callee, new List<ActualBinding>(), expr.to
 04081                s.ResolvedStatements.Add(call);
 04082              }
 04083            } else {
 04084              ResolveExpression(expr, revealResolutionContext);
 04085            }
 04086          }
 04087        }
 04088        foreach (var a in s.ResolvedStatements) {
 04089          ResolveStatement(a, resolutionContext);
 04090        }
 7604404091      } else if (stmt is BreakStmt) {
 04092        var s = (BreakStmt)stmt;
 04093        if (s.TargetLabel != null) {
 04094          Statement target = enclosingStatementLabels.Find(s.TargetLabel.val);
 04095          if (target == null) {
 04096            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"{s.Kind} label is undefined or not in scope: {s.Targ
 04097          } else if (s.IsContinue && !(target is LoopStmt)) {
 04098            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"continue label must designate a loop: {s.TargetLabel
 04099          } else {
 04100            s.TargetStmt = target;
 04101          }
 04102        } else {
 04103          Contract.Assert(1 <= s.BreakAndContinueCount); // follows from BreakStmt class invariant and the guard for thi
 04104          var jumpStmt = s.BreakAndContinueCount == 1 ?
 04105            $"a non-labeled '{s.Kind}' statement" :
 04106            $"a '{Util.Repeat(s.BreakAndContinueCount - 1, "break ")}{s.Kind}' statement";
 04107          if (loopStack.Count == 0) {
 04108            reporter.Error(MessageSource.Resolver, s, $"{jumpStmt} is allowed only in loops");
 04109          } else if (loopStack.Count < s.BreakAndContinueCount) {
 04110            reporter.Error(MessageSource.Resolver, s,
 04111              $"{jumpStmt} is allowed only in contexts with {s.BreakAndContinueCount} enclosing loops, but the current c
 04112          } else {
 04113            Statement target = loopStack[loopStack.Count - s.BreakAndContinueCount];
 04114            if (target.Labels == null) {
 4115              // make sure there is a label, because the compiler and translator will want to see a unique ID
 04116              target.Labels = new LList<Label>(new Label(target.Tok, null), null);
 04117            }
 04118            s.TargetStmt = target;
 04119          }
 04120        }
 4121
 7604404122      } else if (stmt is ProduceStmt) {
 04123        var kind = stmt is YieldStmt ? "yield" : "return";
 04124        if (stmt is YieldStmt && !(resolutionContext.CodeContext is IteratorDecl)) {
 04125          reporter.Error(MessageSource.Resolver, stmt, "yield statement is allowed only in iterators");
 04126        } else if (stmt is ReturnStmt && !(resolutionContext.CodeContext is Method)) {
 04127          reporter.Error(MessageSource.Resolver, stmt, "return statement is allowed only in method");
 04128        } else if (resolutionContext.InFirstPhaseConstructor) {
 04129          reporter.Error(MessageSource.Resolver, stmt, "return statement is not allowed before 'new;' in a constructor")
 04130        }
 04131        var s = (ProduceStmt)stmt;
 04132        if (s.Rhss != null) {
 04133          var cmc = resolutionContext.CodeContext as IMethodCodeContext;
 04134          if (cmc == null) {
 4135            // an error has already been reported above
 04136          } else if (cmc.Outs.Count != s.Rhss.Count) {
 04137            reporter.Error(MessageSource.Resolver, s, "number of {2} parameters does not match declaration (found {0}, e
 04138          } else {
 04139            Contract.Assert(s.Rhss.Count > 0);
 4140            // Create a hidden update statement using the out-parameter formals, resolve the RHS, and check that the RHS
 04141            List<Expression> formals = new List<Expression>();
 04142            foreach (Formal f in cmc.Outs) {
 4143              Expression produceLhs;
 04144              if (stmt is ReturnStmt) {
 04145                var ident = new ImplicitIdentifierExpr(f.tok, f.Name);
 4146                // resolve it here to avoid capture into more closely declared local variables
 04147                ident.Var = f;
 04148                ident.Type = ident.Var.Type;
 04149                Contract.Assert(f.Type != null);
 04150                produceLhs = ident;
 04151              } else {
 04152                var yieldIdent = new MemberSelectExpr(f.tok, new ImplicitThisExpr(f.tok), f.Name);
 04153                ResolveExpression(yieldIdent, resolutionContext);
 04154                produceLhs = yieldIdent;
 04155              }
 04156              formals.Add(produceLhs);
 04157            }
 04158            s.HiddenUpdate = new UpdateStmt(s.RangeToken, formals, s.Rhss, true);
 4159            // resolving the update statement will check for return/yield statement specifics.
 04160            ResolveStatement(s.HiddenUpdate, resolutionContext);
 04161          }
 04162        } else {// this is a regular return/yield statement.
 04163          s.HiddenUpdate = null;
 04164        }
 11004904165      } else if (stmt is VarDeclStmt) {
 3400504166        var s = (VarDeclStmt)stmt;
 4167        // We have four cases.
 3400504168        Contract.Assert(s.Update == null || s.Update is AssignSuchThatStmt || s.Update is UpdateStmt || s.Update is Assi
 4169        // 0.  There is no .Update.  This is easy, we will just resolve the locals.
 4170        // 1.  The .Update is an AssignSuchThatStmt.  This is also straightforward:  first
 4171        //     resolve the locals, which adds them to the scope, and then resolve the .Update.
 4172        // 2.  The .Update is an UpdateStmt, which, resolved, means either a CallStmt or a bunch
 4173        //     of parallel AssignStmt's.  Here, the right-hand sides should be resolved before
 4174        //     the local variables have been added to the scope, but the left-hand sides should
 4175        //     resolve to the newly introduced variables.
 4176        // 3.  The .Update is a ":-" statement, for which resolution does two steps:
 4177        //     First, desugar, then run the regular resolution on the desugared AST.
 4178        // To accommodate these options, we first reach into the UpdateStmt, if any, to resolve
 4179        // the left-hand sides of the UpdateStmt.  This will have the effect of shielding them
 4180        // from a subsequent resolution (since expression resolution will do nothing if the .Type
 4181        // field is already assigned.
 4182        // Alright, so it is:
 4183
 4184        // Resolve the types of the locals
 20579704185        foreach (var local in s.Locals) {
 3459404186          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 3459404187          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 6918804188          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 3459404189            local.type = local.OptionalType;
 3459404190          } else {
 04191            local.type = new InferredTypeProxy();
 04192          }
 3459404193        }
 4194        // Resolve the UpdateStmt, if any
 6801004195        if (s.Update is UpdateStmt) {
 3400504196          var upd = (UpdateStmt)s.Update;
 4197          // resolve the LHS
 3400504198          Contract.Assert(upd.Lhss.Count == s.Locals.Count);
 17179204199          for (int i = 0; i < upd.Lhss.Count; i++) {
 3459404200            var local = s.Locals[i];
 3459404201            var lhs = (IdentifierExpr)upd.Lhss[i];  // the LHS in this case will be an IdentifierExpr, because that's ho
 3459404202            Contract.Assert(lhs.Type == null);  // not yet resolved
 3459404203            lhs.Var = local;
 3459404204            lhs.Type = local.Type;
 3459404205          }
 4206          // resolve the whole thing
 3400504207          s.Update.Resolve(this, resolutionContext);
 3400504208        }
 4209
 3400504210        if (s.Update is AssignOrReturnStmt) {
 04211          var assignOrRet = (AssignOrReturnStmt)s.Update;
 4212          // resolve the LHS
 04213          Contract.Assert(assignOrRet.Lhss.Count == s.Locals.Count);
 04214          for (int i = 0; i < s.Locals.Count; i++) {
 04215            var local = s.Locals[i];
 04216            var lhs = (IdentifierExpr)assignOrRet
 04217              .Lhss[i]; // the LHS in this case will be an IdentifierExpr, because that's how the parser creates the Var
 04218            Contract.Assert(lhs.Type == null); // not yet resolved
 04219            lhs.Var = local;
 04220            lhs.Type = local.Type;
 04221          }
 4222
 4223          // resolve the whole thing
 04224          assignOrRet.Resolve(this, resolutionContext);
 04225        }
 4226        // Add the locals to the scope
 20579704227        foreach (var local in s.Locals) {
 3459404228          ScopePushAndReport(scope, local, "local-variable");
 3459404229        }
 4230        // With the new locals in scope, it's now time to resolve the attributes on all the locals
 20579704231        foreach (var local in s.Locals) {
 3459404232          ResolveAttributes(local, resolutionContext);
 3459404233        }
 4234        // Resolve the AssignSuchThatStmt, if any
 3400504235        if (s.Update is AssignSuchThatStmt assignSuchThatStmt) {
 04236          assignSuchThatStmt.Resolve(this, resolutionContext);
 04237        }
 7604404238      } else if (stmt is VarDeclPattern) {
 04239        VarDeclPattern s = (VarDeclPattern)stmt;
 04240        foreach (var local in s.LocalVars) {
 04241          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04242          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04243          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 04244            local.type = local.OptionalType;
 04245          } else {
 04246            local.type = new InferredTypeProxy();
 04247          }
 04248        }
 04249        ResolveExpression(s.RHS, resolutionContext);
 04250        ResolveCasePattern(s.LHS, s.RHS.Type, resolutionContext);
 4251        // Check for duplicate names now, because not until after resolving the case pattern do we know if identifiers i
 04252        var c = 0;
 04253        foreach (var bv in s.LHS.Vars) {
 04254          ScopePushAndReport(scope, bv, "local_variable");
 04255          c++;
 04256        }
 04257        if (c == 0) {
 4258          // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constant li
 04259          reporter.Error(MessageSource.Resolver, s.LHS.tok, "LHS is a constant literal; to be legal, it must introduce a
 04260        }
 7954904261      } else if (stmt is AssignStmt) {
 3751004262        AssignStmt s = (AssignStmt)stmt;
 3751004263        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 3751004264        ResolveExpression(s.Lhs, resolutionContext);  // allow ghosts for now, tighted up below
 3751004265        bool lhsResolvedSuccessfully = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 3751004266        Contract.Assert(s.Lhs.Type != null);  // follows from postcondition of ResolveExpression
 4267        // check that LHS denotes a mutable variable or a field
 3751004268        var lhs = s.Lhs.Resolved;
 7502004269        if (lhs is IdentifierExpr) {
 3751004270          IVariable var = ((IdentifierExpr)lhs).Var;
 3751004271          if (var == null) {
 4272            // the LHS didn't resolve correctly; some error would already have been reported
 3751004273          } else {
 3751004274            CheckIsLvalue(lhs, resolutionContext);
 3751004275          }
 3751004276        } else if (lhs is MemberSelectExpr) {
 04277          var fse = (MemberSelectExpr)lhs;
 04278          if (fse.Member != null) {  // otherwise, an error was reported above
 04279            CheckIsLvalue(fse, resolutionContext);
 04280          }
 04281        } else if (lhs is SeqSelectExpr) {
 04282          var slhs = (SeqSelectExpr)lhs;
 4283          // LHS is fine, provided the "sequence" is really an array
 04284          if (lhsResolvedSuccessfully) {
 04285            Contract.Assert(slhs.Seq.Type != null);
 04286            CheckIsLvalue(slhs, resolutionContext);
 04287          }
 04288        } else if (lhs is MultiSelectExpr) {
 04289          CheckIsLvalue(lhs, resolutionContext);
 04290        } else {
 04291          CheckIsLvalue(lhs, resolutionContext);
 04292        }
 3751004293        Type lhsType = s.Lhs.Type;
 7502004294        if (s.Rhs is ExprRhs) {
 3751004295          ExprRhs rr = (ExprRhs)s.Rhs;
 3751004296          ResolveExpression(rr.Expr, resolutionContext);
 3751004297          Contract.Assert(rr.Expr.Type != null);  // follows from postcondition of ResolveExpression
 4298
 3751004299          if (s.Lhs is ImplicitIdentifierExpr { Var: Formal { InParam: false } }) {
 04300            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "Method return value mismatch (expected {0}, got {1
 3751004301          } else {
 3751004302            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "RHS (of type {1}) not assignable to LHS (of type {
 3751004303          }
 3751004304        } else if (s.Rhs is TypeRhs) {
 04305          TypeRhs rr = (TypeRhs)s.Rhs;
 04306          Type t = ResolveTypeRhs(rr, stmt, resolutionContext);
 04307          AddAssignableConstraint(stmt.Tok, lhsType, t, "type {1} is not assignable to LHS (of type {0})");
 04308        } else if (s.Rhs is HavocRhs) {
 4309          // nothing else to do
 04310        } else {
 04311          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected RHS
 4312        }
 4313
 4321804314      } else if (stmt is CallStmt) {
 117904315        CallStmt s = (CallStmt)stmt;
 117904316        ResolveCallStmt(s, resolutionContext, null);
 4317
 728904318      } else if (stmt is BlockStmt) {
 276004319        var s = (BlockStmt)stmt;
 276004320        scope.PushMarker();
 276004321        ResolveBlockStatement(s, resolutionContext);
 276004322        scope.PopMarker();
 4323
 394004324      } else if (stmt is IfStmt) {
 59004325        IfStmt s = (IfStmt)stmt;
 118004326        if (s.Guard != null) {
 59004327          ResolveExpression(s.Guard, resolutionContext);
 59004328          Contract.Assert(s.Guard.Type != null);  // follows from postcondition of ResolveExpression
 59004329          ConstrainTypeExprBool(s.Guard, "condition is expected to be of type bool, but is {0}");
 59004330        }
 4331
 59004332        scope.PushMarker();
 59004333        if (s.IsBindingGuard) {
 04334          var exists = (ExistsExpr)s.Guard;
 04335          foreach (var v in exists.BoundVars) {
 04336            ScopePushAndReport(scope, v, "bound-variable");
 04337          }
 04338        }
 59004339        DominatingStatementLabels.PushMarker();
 59004340        ResolveBlockStatement(s.Thn, resolutionContext);
 59004341        DominatingStatementLabels.PopMarker();
 59004342        scope.PopMarker();
 4343
 118004344        if (s.Els != null) {
 59004345          DominatingStatementLabels.PushMarker();
 59004346          ResolveStatement(s.Els, resolutionContext);
 59004347          DominatingStatementLabels.PopMarker();
 59004348        }
 4349
 59004350      } else if (stmt is AlternativeStmt) {
 04351        var s = (AlternativeStmt)stmt;
 04352        ResolveAlternatives(s.Alternatives, null, resolutionContext);
 4353
 04354      } else if (stmt is OneBodyLoopStmt) {
 04355        var s = (OneBodyLoopStmt)stmt;
 04356        if (s is WhileStmt whileS && whileS.Guard != null) {
 04357          ResolveExpression(whileS.Guard, resolutionContext);
 04358          Contract.Assert(whileS.Guard.Type != null);  // follows from postcondition of ResolveExpression
 04359          ConstrainTypeExprBool(whileS.Guard, "condition is expected to be of type bool, but is {0}");
 04360        } else if (s is ForLoopStmt forS) {
 04361          var loopIndex = forS.LoopIndex;
 04362          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04363          ResolveType(loopIndex.Tok, loopIndex.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04364          var err = new TypeConstraint.ErrorMsgWithToken(loopIndex.Tok, "index variable is expected to be of an integer 
 04365          ConstrainToIntegerType(loopIndex.Tok, loopIndex.Type, false, err);
 4366
 04367          ResolveExpression(forS.Start, resolutionContext);
 04368          AddAssignableConstraint(forS.Start.tok, forS.LoopIndex.Type, forS.Start.Type, "lower bound (of type {1}) not a
 04369          if (forS.End != null) {
 04370            ResolveExpression(forS.End, resolutionContext);
 04371            AddAssignableConstraint(forS.End.tok, forS.LoopIndex.Type, forS.End.Type, "upper bound (of type {1}) not ass
 04372            if (forS.Decreases.Expressions.Count != 0) {
 04373              reporter.Error(MessageSource.Resolver, forS.Decreases.Expressions[0].tok,
 04374                "a 'for' loop is allowed an explicit 'decreases' clause only if the end-expression is '*'");
 04375            }
 04376          } else if (forS.Decreases.Expressions.Count == 0 && !resolutionContext.CodeContext.AllowsNontermination) {
 4377            // note, the following error message is also emitted elsewhere (if the loop bears a "decreases *")
 04378            reporter.Error(MessageSource.Resolver, forS.Tok,
 04379              "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be p
 04380              " (or you can add a 'decreases' clause to this 'for' loop if you want to prove that it does indeed termina
 04381          }
 4382
 4383          // Create a new scope, add the local to the scope, and resolve the attributes
 04384          scope.PushMarker();
 04385          ScopePushAndReport(scope, loopIndex, "index-variable");
 04386          ResolveAttributes(s, resolutionContext);
 04387        }
 4388
 04389        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4390
 04391        if (s.Body != null) {
 04392          loopStack.Add(s);  // push
 04393          DominatingStatementLabels.PushMarker();
 04394          ResolveStatement(s.Body, resolutionContext);
 04395          DominatingStatementLabels.PopMarker();
 04396          loopStack.RemoveAt(loopStack.Count - 1);  // pop
 04397        }
 4398
 04399        if (s is ForLoopStmt) {
 04400          scope.PopMarker();
 04401        }
 4402
 04403      } else if (stmt is AlternativeLoopStmt) {
 04404        var s = (AlternativeLoopStmt)stmt;
 04405        ResolveAlternatives(s.Alternatives, s, resolutionContext);
 04406        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4407
 04408      } else if (stmt is ForallStmt) {
 04409        var s = (ForallStmt)stmt;
 4410
 04411        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04412        scope.PushMarker();
 04413        foreach (BoundVar v in s.BoundVars) {
 04414          ScopePushAndReport(scope, v, "local-variable");
 04415          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04416        }
 04417        ResolveExpression(s.Range, resolutionContext);
 04418        Contract.Assert(s.Range.Type != null);  // follows from postcondition of ResolveExpression
 04419        ConstrainTypeExprBool(s.Range, "range restriction in forall statement must be of type bool (instead got {0})");
 04420        foreach (var ens in s.Ens) {
 04421          ResolveExpression(ens.E, resolutionContext);
 04422          Contract.Assert(ens.E.Type != null);  // follows from postcondition of ResolveExpression
 04423          ConstrainTypeExprBool(ens.E, "ensures condition is expected to be of type bool, but is {0}");
 04424        }
 4425        // Since the range and postconditions are more likely to infer the types of the bound variables, resolve them
 4426        // first (above) and only then resolve the attributes (below).
 04427        ResolveAttributes(s, resolutionContext);
 4428
 04429        if (s.Body != null) {
 4430          // clear the labels for the duration of checking the body, because break statements are not allowed to leave a
 04431          var prevLblStmts = enclosingStatementLabels;
 04432          var prevLoopStack = loopStack;
 04433          enclosingStatementLabels = new Scope<Statement>(Options);
 04434          loopStack = new List<Statement>();
 04435          ResolveStatement(s.Body, resolutionContext);
 04436          enclosingStatementLabels = prevLblStmts;
 04437          loopStack = prevLoopStack;
 04438        }
 04439        scope.PopMarker();
 4440
 04441        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 4442          // determine the Kind and run some additional checks on the body
 04443          if (s.Ens.Count != 0) {
 4444            // The only supported kind with ensures clauses is Proof.
 04445            s.Kind = ForallStmt.BodyKind.Proof;
 04446          } else {
 4447            // There are three special cases:
 4448            // * Assign, which is the only kind of the forall statement that allows a heap update.
 4449            // * Call, which is a single call statement with no side effects or output parameters.
 4450            // * A single calc statement, which is a special case of Proof where the postcondition can be inferred.
 4451            // The effect of Assign and the postcondition of Call will be seen outside the forall
 4452            // statement.
 04453            Statement s0 = s.S0;
 04454            if (s0 is AssignStmt) {
 04455              s.Kind = ForallStmt.BodyKind.Assign;
 4456
 04457              var rhs = ((AssignStmt)s0).Rhs;
 04458              if (rhs is TypeRhs) {
 04459                reporter.Error(MessageSource.Resolver, rhs.Tok, "new allocation not supported in aggregate assignments")
 04460              }
 4461
 04462            } else if (s0 is CallStmt) {
 04463              s.Kind = ForallStmt.BodyKind.Call;
 04464              var call = (CallStmt)s.S0;
 04465              var method = call.Method;
 4466              // if the called method is not in the same module as the ForallCall stmt
 4467              // don't convert it to ForallExpression since the inlined called method's
 4468              // ensure clause might not be resolved correctly(test\dafny3\GenericSort.dfy)
 04469              if (method.EnclosingClass.EnclosingModuleDefinition != resolutionContext.CodeContext.EnclosingModule) {
 04470                s.CanConvert = false;
 04471              }
 4472              // Additional information (namely, the postcondition of the call) will be reported later. But it cannot be
 4473              // done yet, because the specification of the callee may not have been resolved yet.
 04474            } else if (s0 is CalcStmt) {
 04475              s.Kind = ForallStmt.BodyKind.Proof;
 4476              // add the conclusion of the calc as a free postcondition
 04477              var result = ((CalcStmt)s0).Result;
 04478              s.Ens.Add(new AttributedExpression(result));
 04479              reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(Options, result));
 04480            } else {
 04481              s.Kind = ForallStmt.BodyKind.Proof;
 04482              if (s.Body is BlockStmt && ((BlockStmt)s.Body).Body.Count == 0) {
 4483                // an empty statement, so don't produce any warning
 04484              } else {
 04485                reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, s.Tok, "the conclusion of the body of thi
 04486              }
 04487            }
 04488          }
 4489
 04490          if (s.ForallExpressions != null) {
 04491            foreach (Expression expr in s.ForallExpressions) {
 04492              ResolveExpression(expr, resolutionContext);
 04493            }
 04494          }
 04495        }
 4496
 04497      } else if (stmt is ModifyStmt) {
 04498        var s = (ModifyStmt)stmt;
 04499        ResolveAttributes(s.Mod, resolutionContext);
 04500        foreach (FrameExpression fe in s.Mod.Expressions) {
 04501          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04502        }
 04503        if (s.Body != null) {
 04504          ResolveBlockStatement(s.Body, resolutionContext);
 04505        }
 4506
 04507      } else if (stmt is CalcStmt) {
 04508        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04509        CalcStmt s = (CalcStmt)stmt;
 4510        // figure out s.Op
 04511        Contract.Assert(s.Op == null);  // it hasn't been set yet
 04512        if (s.UserSuppliedOp != null) {
 04513          s.Op = s.UserSuppliedOp;
 04514        } else {
 04515          s.Op = s.GetInferredDefaultOp() ?? CalcStmt.DefaultOp;
 04516          reporter.Info(MessageSource.Resolver, s.Tok, s.Op.ToString());
 04517        }
 4518
 04519        if (s.Lines.Count > 0) {
 04520          Type lineType = new InferredTypeProxy();
 04521          var e0 = s.Lines.First();
 04522          ResolveExpression(e0, resolutionContext);
 04523          Contract.Assert(e0.Type != null);  // follows from postcondition of ResolveExpression
 04524          var err = new TypeConstraint.ErrorMsgWithToken(e0.tok, "all lines in a calculation must have the same type (go
 04525          ConstrainSubtypeRelation(lineType, e0.Type, err);
 04526          for (int i = 1; i < s.Lines.Count; i++) {
 04527            var e1 = s.Lines[i];
 04528            ResolveExpression(e1, resolutionContext);
 04529            Contract.Assert(e1.Type != null);  // follows from postcondition of ResolveExpression
 4530            // reuse the error object if we're on the dummy line; this prevents a duplicate error message
 04531            if (i < s.Lines.Count - 1) {
 04532              err = new TypeConstraint.ErrorMsgWithToken(e1.tok, "all lines in a calculation must have the same type (go
 04533            }
 04534            ConstrainSubtypeRelation(lineType, e1.Type, err);
 04535            var step = (s.StepOps[i - 1] ?? s.Op).StepExpr(e0, e1); // Use custom line operator
 04536            ResolveExpression(step, resolutionContext);
 04537            s.Steps.Add(step);
 04538            e0 = e1;
 04539          }
 4540
 4541          // clear the labels for the duration of checking the hints, because break statements are not allowed to leave 
 04542          var prevLblStmts = enclosingStatementLabels;
 04543          var prevLoopStack = loopStack;
 04544          enclosingStatementLabels = new Scope<Statement>(Options);
 04545          loopStack = new List<Statement>();
 04546          foreach (var h in s.Hints) {
 04547            foreach (var oneHint in h.Body) {
 04548              DominatingStatementLabels.PushMarker();
 04549              ResolveStatement(oneHint, resolutionContext);
 04550              DominatingStatementLabels.PopMarker();
 04551            }
 04552          }
 04553          enclosingStatementLabels = prevLblStmts;
 04554          loopStack = prevLoopStack;
 4555
 04556        }
 04557        if (prevErrorCount == reporter.Count(ErrorLevel.Error) && s.Lines.Count > 0) {
 4558          // do not build Result from the lines if there were errors, as it might be ill-typed and produce unnecessary r
 04559          var resultOp = s.StepOps.Aggregate(s.Op, (op0, op1) => op1 == null ? op0 : op0.ResultOp(op1));
 04560          s.Result = resultOp.StepExpr(s.Lines.First(), s.Lines.Last());
 04561        } else {
 04562          s.Result = CalcStmt.DefaultOp.StepExpr(Expression.CreateIntLiteral(s.Tok, 0), Expression.CreateIntLiteral(s.To
 04563        }
 04564        ResolveExpression(s.Result, resolutionContext);
 04565        Contract.Assert(s.Result != null);
 04566        Contract.Assert(prevErrorCount != reporter.Count(ErrorLevel.Error) || s.Steps.Count == s.Hints.Count);
 4567
 04568      } else if (stmt is SkeletonStatement) {
 04569        var s = (SkeletonStatement)stmt;
 04570        reporter.Error(MessageSource.Resolver, s.Tok, "skeleton statements are allowed only in refining methods");
 4571        // nevertheless, resolve the underlying statement; hey, why not
 04572        if (s.S != null) {
 04573          ResolveStatement(s.S, resolutionContext);
 04574        }
 04575      } else {
 04576        Contract.Assert(false); throw new cce.UnreachableException();
 4577      }
 8478004578    }
 4579
 4580    private void ResolveLoopSpecificationComponents(List<AttributedExpression> invariants, Specification<Expression> dec
 04581      Specification<FrameExpression> modifies, ResolutionContext resolutionContext) {
 4582      Contract.Requires(invariants != null);
 4583      Contract.Requires(decreases != null);
 4584      Contract.Requires(modifies != null);
 4585      Contract.Requires(resolutionContext != null);
 4586
 04587      foreach (AttributedExpression inv in invariants) {
 04588        ResolveAttributes(inv, resolutionContext);
 04589        ResolveExpression(inv.E, resolutionContext);
 04590        Contract.Assert(inv.E.Type != null);  // follows from postcondition of ResolveExpression
 04591        ConstrainTypeExprBool(inv.E, "invariant is expected to be of type bool, but is {0}");
 04592      }
 4593
 04594      ResolveAttributes(decreases, resolutionContext);
 04595      foreach (Expression e in decreases.Expressions) {
 04596        ResolveExpression(e, resolutionContext);
 04597        if (e is WildcardExpr && !resolutionContext.CodeContext.AllowsNontermination) {
 04598          reporter.Error(MessageSource.Resolver, e, "a possibly infinite loop is allowed only if the enclosing method is
 04599        }
 4600        // any type is fine
 04601      }
 4602
 04603      ResolveAttributes(modifies, resolutionContext);
 04604      if (modifies.Expressions != null) {
 04605        foreach (FrameExpression fe in modifies.Expressions) {
 04606          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04607        }
 04608      }
 04609    }
 4610
 4611    /// <summary>
 4612    /// Resolves the default-valued expression for each formal in "formals".
 4613    /// Solves the resulting type constraints.
 4614    /// Assumes these are the only type constraints to be solved.
 4615    ///
 4616    /// Reports an error for any cyclic dependency among the default-value expressions of the formals.
 4617    /// </summary>
 179704618    public void ResolveParameterDefaultValues(List<Formal> formals, ResolutionContext resolutionContext) {
 4619      Contract.Requires(formals != null);
 4620      Contract.Requires(resolutionContext != null);
 4621
 179704622      Contract.Assume(AllTypeConstraints.Count == 0);
 4623
 4624      // Formal parameters have three ways to indicate how they are to be passed in:
 4625      //   * nameonly: the only way to give a specific argument value is to name the parameter
 4626      //   * positional only: these are nameless parameters (which are allowed only for datatype constructor parameters)
 4627      //   * either positional or by name: this is the most common parameter
 4628      // A parameter is either required or optional:
 4629      //   * required: a caller has to supply an argument
 4630      //   * optional: the parameter has a default value that is used if a caller omits passing a specific argument
 4631      //
 4632      // The syntax for giving a positional-only (i.e., nameless) parameter does not allow a default-value expression, s
 4633      // a positional-only parameter is always required.
 4634      //
 4635      // At a call site, positional arguments are not allowed to follow named arguments. Therefore, if "x" is
 4636      // a nameonly parameter, then there is no way to supply the parameters after "x" by position. Thus, any
 4637      // parameter that follows "x" must either be passed by name or have a default value. That is, if a later
 4638      // parameter does not have a default value, it is _effectively_ nameonly. We impose the rule that
 4639      //   * an effectively nameonly parameter must be declared as nameonly
 4640      //
 4641      // For a positional-only parameter "x", every parameter preceding "x" is _effectively_ required. We impose
 4642      // the rule that
 4643      //   * an effectively required parameter must not have a default-value expression
 179704644      var dependencies = new Graph<IVariable>();
 179704645      string nameOfMostRecentNameonlyParameter = null;
 179704646      var previousParametersWithDefaultValue = new HashSet<Formal>();
 1873504647      foreach (var formal in formals) {
 444804648        if (!formal.HasName) {
 04649          foreach (var previousFormal in previousParametersWithDefaultValue) {
 04650            reporter.Error(MessageSource.Resolver, previousFormal.DefaultValue.tok,
 04651              $"because of a later nameless parameter, this default value is never used; remove it or name all subsequen
 04652          }
 04653          previousParametersWithDefaultValue.Clear();
 04654        }
 444804655        var d = formal.DefaultValue;
 444804656        if (d != null) {
 04657          ResolveExpression(d, resolutionContext);
 04658          AddAssignableConstraint(d.tok, formal.Type, d.Type, "default-value expression (of type '{1}') is not assignabl
 04659          foreach (var v in FreeVariables(d)) {
 04660            dependencies.AddEdge(formal, v);
 04661          }
 04662          previousParametersWithDefaultValue.Add(formal);
 444804663        } else if (nameOfMostRecentNameonlyParameter != null && !formal.IsNameOnly) {
 4664          // "formal" is preceded by a nameonly parameter, but itself is neither nameonly nor has a default value
 04665          reporter.Error(MessageSource.Resolver, formal.tok,
 04666            $"this parameter is effectively nameonly (because of the earlier nameonly parameter '{nameOfMostRecentNameon
 04667            "declare it as nameonly or give it a default-value expression");
 04668        }
 444804669        if (formal.IsNameOnly) {
 04670          nameOfMostRecentNameonlyParameter = formal.Name;
 04671        }
 444804672      }
 179704673      SolveAllTypeConstraints();
 4674
 539104675      foreach (var cycle in dependencies.AllCycles()) {
 04676        var cy = Util.Comma(" -> ", cycle, v => v.Name) + " -> " + cycle[0].Name;
 04677        reporter.Error(MessageSource.Resolver, cycle[0], $"default-value expressions for parameters contain a cycle: {cy
 04678      }
 179704679    }
 4680
 4681    /// <summary>
 4682    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4683    /// </summary>
 4635904684    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOptionEnum eopt, List
 4685      Contract.Requires(tok != null);
 4686      Contract.Requires(type != null);
 4687      Contract.Requires(resolutionContext != null);
 4688      Contract.Requires(eopt != ResolveTypeOptionEnum.AllowPrefixExtend);
 4635904689      ResolveType(tok, type, resolutionContext, new ResolveTypeOption(eopt), defaultTypeArguments);
 4635904690    }
 4691
 8304692    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOptionEnum eopt, List<TypePa
 8304693      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), eopt, defaultTypeArguments);
 8304694    }
 4695
 654004696    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOption option, List<TypePara
 654004697      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), option, defaultTypeArguments);
 654004698    }
 4699
 6616854700    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 4701      Contract.Requires(tok != null);
 4702      Contract.Requires(type != null);
 4703      Contract.Requires(resolutionContext != null);
 4704      Contract.Requires(option != null);
 4705      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6616854706      var r = ResolveTypeLenient(tok, type, resolutionContext, option, defaultTypeArguments, false);
 6616854707      Contract.Assert(r == null);
 6616854708    }
 4709
 4710    public class ResolveTypeReturn {
 4711      public readonly Type ReplacementType;
 4712      public readonly ExprDotName LastComponent;
 04713      public ResolveTypeReturn(Type replacementType, ExprDotName lastComponent) {
 4714        Contract.Requires(replacementType != null);
 4715        Contract.Requires(lastComponent != null);
 04716        ReplacementType = replacementType;
 04717        LastComponent = lastComponent;
 04718      }
 4719    }
 4720    /// <summary>
 4721    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4722    /// One more thing:  if "allowDanglingDotName" is true, then if the resolution would have produced
 4723    ///   an error message that could have been avoided if "type" denoted an identifier sequence one
 4724    ///   shorter, then return an unresolved replacement type where the identifier sequence is one
 4725    ///   shorter.  (In all other cases, the method returns null.)
 4726    /// </summary>
 6616854727    public ResolveTypeReturn ResolveTypeLenient(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeO
 4728      Contract.Requires(tok != null);
 4729      Contract.Requires(type != null);
 4730      Contract.Requires(resolutionContext != null);
 4731      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6616854732      if (type is BitvectorType) {
 04733        var t = (BitvectorType)type;
 4734        // nothing to resolve, but record the fact that this bitvector width is in use
 04735        builtIns.Bitwidths.Add(t.Width);
 7700354736      } else if (type is BasicType) {
 4737        // nothing to resolve
 6616854738      } else if (type is MapType) {
 04739        var mt = (MapType)type;
 04740        var errorCount = reporter.Count(ErrorLevel.Error);
 4741        int typeArgumentCount;
 04742        if (mt.HasTypeArg()) {
 04743          ResolveType(tok, mt.Domain, resolutionContext, option, defaultTypeArguments);
 04744          ResolveType(tok, mt.Range, resolutionContext, option, defaultTypeArguments);
 04745          typeArgumentCount = 2;
 04746        } else if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 04747          mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04748          typeArgumentCount = 0;
 04749        } else {
 04750          var inferredTypeArgs = new List<Type>();
 04751          FillInTypeArguments(tok, 2, inferredTypeArgs, defaultTypeArguments, option);
 04752          Contract.Assert(inferredTypeArgs.Count <= 2);
 04753          if (inferredTypeArgs.Count == 1) {
 04754            mt.SetTypeArgs(inferredTypeArgs[0], new InferredTypeProxy());
 04755            typeArgumentCount = 1;
 04756          } else if (inferredTypeArgs.Count == 2) {
 04757            mt.SetTypeArgs(inferredTypeArgs[0], inferredTypeArgs[1]);
 04758            typeArgumentCount = 2;
 04759          } else {
 04760            mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04761            typeArgumentCount = 0;
 04762          }
 04763        }
 4764        // defaults and auto have been applied; check if we now have the right number of arguments
 04765        if (2 != typeArgumentCount) {
 04766          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of 2) passed to type:
 04767        }
 6199754768      } else if (type is CollectionType) {
 666404769        var t = (CollectionType)type;
 666404770        var errorCount = reporter.Count(ErrorLevel.Error);
 1332804771        if (t.HasTypeArg()) {
 666404772          ResolveType(tok, t.Arg, resolutionContext, option, defaultTypeArguments);
 666404773        } else if (option.Opt != ResolveTypeOptionEnum.DontInfer) {
 04774          var inferredTypeArgs = new List<Type>();
 04775          FillInTypeArguments(tok, 1, inferredTypeArgs, defaultTypeArguments, option);
 04776          if (inferredTypeArgs.Count != 0) {
 04777            Contract.Assert(inferredTypeArgs.Count == 1);
 04778            t.SetTypeArg(inferredTypeArgs[0]);
 04779          }
 04780        }
 666404781        if (!t.HasTypeArg()) {
 4782          // defaults and auto have been applied; check if we now have the right number of arguments
 04783          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments (0 instead of 1) passed to type: {
 4784          // add a proxy type, to make sure that CollectionType will have have a non-null Arg
 04785          t.SetTypeArg(new InferredTypeProxy());
 04786        }
 4787
 6786604788      } else if (type is UserDefinedType) {
 1253254789        var t = (UserDefinedType)type;
 1257404790        if (t.ResolvedClass != null) {
 4791          // Apparently, this type has already been resolved
 4154792          return null;
 4793        }
 1249104794        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 1249104795        if (t.NamePath is ExprDotName) {
 04796          var ret = ResolveDotSuffix_Type((ExprDotName)t.NamePath, resolutionContext, allowDanglingDotName, option, defa
 04797          if (ret != null) {
 04798            return ret;
 4799          }
 1249104800        } else {
 1249104801          var s = (NameSegment)t.NamePath;
 1249104802          ResolveNameSegment_Type(s, resolutionContext, option, defaultTypeArguments);
 1249104803        }
 2498204804        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 1249104805          var r = t.NamePath.Resolved as Resolver_IdentifierExpr;
 1249104806          if (r == null || !(r.Type is Resolver_IdentifierExpr.ResolverType_Type)) {
 04807            reporter.Error(MessageSource.Resolver, t.tok, "expected type");
 2498204808          } else if (r.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 1249104809            var d = r.Decl;
 1249104810            if (d is AbstractTypeDecl) {
 4811              // resolve like a type parameter, and it may have type parameters if it's an abstract type
 04812              t.ResolvedClass = d;  // Store the decl, so the compiler will generate the fully qualified name
 1941404813            } else if (d is RedirectingTypeDecl) {
 692304814              var dd = (RedirectingTypeDecl)d;
 692304815              var caller = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) as ICallable;
 1376304816              if (caller != null && !(d is SubsetTypeDecl && caller is SpecialFunction)) {
 1368004817                if (caller != d) {
 684004818                } else if (d is TypeSynonymDecl && !(d is SubsetTypeDecl)) {
 4819                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04820                  reporter.Error(MessageSource.Resolver, d.tok, "type-synonym cycle: {0} -> {0}", d.Name);
 04821                } else {
 4822                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04823                  reporter.Error(MessageSource.Resolver, d.tok, "recursive constraint dependency involving a {0}: {1} ->
 04824                }
 684004825              }
 692304826              t.ResolvedClass = d;
 1631604827            } else if (d is DatatypeDecl) {
 382504828              t.ResolvedClass = d;
 556804829            } else {
 4830              // d is a type parameter, coinductive datatype, or class, and it may have type parameters
 174304831              t.ResolvedClass = d;
 174304832            }
 1898804833            if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 4834              // don't add anything
 1249104835            } else if (d.TypeArgs.Count != t.TypeArgs.Count && t.TypeArgs.Count == 0) {
 04836              FillInTypeArguments(t.tok, d.TypeArgs.Count, t.TypeArgs, defaultTypeArguments, option);
 04837            }
 4838            // defaults and auto have been applied; check if we now have the right number of arguments
 1249104839            if (d.TypeArgs.Count != t.TypeArgs.Count) {
 04840              reporter.Error(MessageSource.Resolver, t.tok, "Wrong number of type arguments ({0} instead of {1}) passed 
 04841            }
 4842
 1249104843          }
 1249104844        }
 1249104845        if (t.ResolvedClass == null) {
 4846          // There was some error. Still, we will set .ResolvedClass to some value to prevent some crashes in the downst
 4847          // 0-tuple is convenient, because it is always in scope.
 04848          t.ResolvedClass = builtIns.TupleType(t.tok, 0, false);
 4849          // clear out the TypeArgs since 0-tuple doesn't take TypeArg
 04850          t.TypeArgs = new List<Type>();
 04851        }
 4852
 8468204853      } else if (type is TypeProxy) {
 3605404854        TypeProxy t = (TypeProxy)type;
 3605404855        if (t.T != null) {
 04856          ResolveType(tok, t.T, resolutionContext, option, defaultTypeArguments);
 04857        }
 3622004858      } else if (type is SelfType) {
 4859        // do nothing.
 8304860      } else {
 04861        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4862      }
 6612704863      return null;
 6616854864    }
 4865
 4866    /// <summary>
 4867    /// Adds to "typeArgs" a list of "n" type arguments, possibly extending "defaultTypeArguments".
 4868    /// </summary>
 04869    static void FillInTypeArguments(IToken tok, int n, List<Type> typeArgs, List<TypeParameter> defaultTypeArguments, Re
 4870      Contract.Requires(tok != null);
 4871      Contract.Requires(0 <= n);
 4872      Contract.Requires(typeArgs != null && typeArgs.Count == 0);
 04873      if (option.Opt == ResolveTypeOptionEnum.InferTypeProxies) {
 4874        // add type arguments that will be inferred
 04875        for (int i = 0; i < n; i++) {
 04876          typeArgs.Add(new InferredTypeProxy());
 04877        }
 04878      } else if (option.Opt == ResolveTypeOptionEnum.AllowPrefix && defaultTypeArguments.Count < n) {
 4879        // there aren't enough default arguments, so don't do anything
 04880      } else {
 4881        // we'll add arguments
 04882        if (option.Opt == ResolveTypeOptionEnum.AllowPrefixExtend) {
 4883          // extend defaultTypeArguments, if needed
 04884          for (int i = defaultTypeArguments.Count; i < n; i++) {
 04885            var tp = new TypeParameter(tok.ToRange(), new Name(tok.ToRange(), "_T" + i), i, option.Parent);
 04886            if (option.Parent is IteratorDecl) {
 04887              tp.Characteristics.AutoInit = Type.AutoInitInfo.CompilableValue;
 04888            }
 04889            defaultTypeArguments.Add(tp);
 04890          }
 04891        }
 04892        Contract.Assert(n <= defaultTypeArguments.Count);
 4893        // automatically supply a prefix of the arguments from defaultTypeArguments
 04894        for (int i = 0; i < n; i++) {
 04895          typeArgs.Add(new UserDefinedType(defaultTypeArguments[i]));
 04896        }
 04897      }
 04898    }
 4899
 8304900    public static bool TypeConstraintsIncludeProxy(Type t, TypeProxy proxy) {
 8304901      return TypeConstraintsIncludeProxy_Aux(t, proxy, new HashSet<TypeProxy>());
 8304902    }
 12454903    static bool TypeConstraintsIncludeProxy_Aux(Type t, TypeProxy proxy, ISet<TypeProxy> visited) {
 4904      Contract.Requires(t != null);
 4905      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);  // t is expected to have been normalized first
 4906      Contract.Requires(proxy != null && proxy.T == null);
 4907      Contract.Requires(visited != null);
 12454908      var tproxy = t as TypeProxy;
 12454909      if (tproxy != null) {
 04910        if (object.ReferenceEquals(tproxy, proxy)) {
 04911          return true;
 04912        } else if (visited.Contains(tproxy)) {
 04913          return false;
 4914        }
 04915        visited.Add(tproxy);
 04916        foreach (var su in tproxy.Subtypes) {
 04917          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04918            return true;
 4919          }
 04920        }
 04921        foreach (var su in tproxy.Supertypes) {
 04922          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04923            return true;
 4924          }
 04925        }
 12454926      } else {
 4927        // check type arguments of t
 49804928        foreach (var ta in t.TypeArgs) {
 4154929          var a = ta.Normalize();
 4154930          if (TypeConstraintsIncludeProxy_Aux(a, proxy, visited)) {
 04931            return true;
 4932          }
 4154933        }
 12454934      }
 12454935      return false;
 12454936    }
 4937
 04938    public Type ResolveTypeRhs(TypeRhs rr, Statement stmt, ResolutionContext resolutionContext) {
 4939      Contract.Requires(rr != null);
 4940      Contract.Requires(stmt != null);
 4941      Contract.Requires(resolutionContext != null);
 4942      Contract.Ensures(Contract.Result<Type>() != null);
 4943
 04944      if (rr.Type == null) {
 04945        if (rr.ArrayDimensions != null) {
 4946          // ---------- new T[EE]    OR    new T[EE] (elementInit)
 04947          Contract.Assert(rr.Bindings == null && rr.Path == null && rr.InitCall == null);
 04948          ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04949          int i = 0;
 04950          foreach (Expression dim in rr.ArrayDimensions) {
 04951            Contract.Assert(dim != null);
 04952            ResolveExpression(dim, resolutionContext);
 04953            ConstrainToIntegerType(dim, false, string.Format("new must use an integer-based expression for the array siz
 04954            i++;
 04955          }
 04956          rr.Type = ResolvedArrayType(stmt.Tok, rr.ArrayDimensions.Count, rr.EType, resolutionContext, false);
 04957          if (rr.ElementInit != null) {
 04958            ResolveExpression(rr.ElementInit, resolutionContext);
 4959            // Check
 4960            //     int^N -> rr.EType  :>  rr.ElementInit.Type
 04961            builtIns.CreateArrowTypeDecl(rr.ArrayDimensions.Count);  // TODO: should this be done already in the parser?
 04962            var args = new List<Type>();
 04963            for (int ii = 0; ii < rr.ArrayDimensions.Count; ii++) {
 04964              args.Add(builtIns.Nat());
 04965            }
 04966            var arrowType = new ArrowType(rr.ElementInit.tok, builtIns.ArrowTypeDecls[rr.ArrayDimensions.Count], args, r
 04967            var lambdaType = rr.ElementInit.Type.AsArrowType;
 04968            if (lambdaType != null && lambdaType.TypeArgs[0] is InferredTypeProxy) {
 04969              (lambdaType.TypeArgs[0] as InferredTypeProxy).KeepConstraints = true;
 04970            }
 4971            string underscores;
 04972            if (rr.ArrayDimensions.Count == 1) {
 04973              underscores = "_";
 04974            } else {
 04975              underscores = "(" + Util.Comma(rr.ArrayDimensions.Count, x => "_") + ")";
 04976            }
 04977            var hintString = string.Format(" (perhaps write '{0} =>' in front of the expression you gave in order to mak
 04978            ConstrainSubtypeRelation(arrowType, rr.ElementInit.Type, rr.ElementInit, "array-allocation initialization ex
 04979              arrowType, rr.ElementInit.Type, new LazyString_OnTypeEquals(rr.EType, rr.ElementInit.Type, hintString));
 04980          } else if (rr.InitDisplay != null) {
 04981            foreach (var v in rr.InitDisplay) {
 04982              ResolveExpression(v, resolutionContext);
 04983              AddAssignableConstraint(v.tok, rr.EType, v.Type, "initial value must be assignable to array's elements (ex
 04984            }
 04985          }
 04986        } else {
 04987          bool callsConstructor = false;
 04988          if (rr.Bindings == null) {
 04989            ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04990            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 04991            if (cl != null && !(rr.EType.IsTraitType && !rr.EType.NormalizeExpand().IsObjectQ)) {
 4992              // life is good
 04993            } else {
 04994              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 04995            }
 04996          } else {
 04997            string initCallName = null;
 04998            IToken initCallTok = null;
 4999            // Resolve rr.Path and do one of three things:
 5000            // * If rr.Path denotes a type, then set EType,initCallName to rr.Path,"_ctor", which sets up a call to the 
 5001            // * If the all-but-last components of rr.Path denote a type, then do EType,initCallName := allButLast(EType
 5002            // * Otherwise, report an error
 05003            var ret = ResolveTypeLenient(rr.Tok, rr.Path, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum
 05004            if (ret != null) {
 5005              // The all-but-last components of rr.Path denote a type (namely, ret.ReplacementType).
 05006              rr.EType = ret.ReplacementType;
 05007              initCallName = ret.LastComponent.SuffixName;
 05008              initCallTok = ret.LastComponent.tok;
 05009            } else {
 5010              // Either rr.Path resolved correctly as a type or there was no way to drop a last component to make it int
 5011              // like a type.  In either case, set EType,initCallName to Path,"_ctor" and continue.
 05012              rr.EType = rr.Path;
 05013              initCallName = "_ctor";
 05014              initCallTok = rr.Tok;
 05015            }
 05016            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 05017            if (cl == null || rr.EType.IsTraitType) {
 05018              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 05019            } else {
 5020              // ---------- new C.Init(EE)
 05021              Contract.Assert(initCallName != null);
 05022              var prevErrorCount = reporter.Count(ErrorLevel.Error);
 5023
 5024              // We want to create a MemberSelectExpr for the initializing method.  To do that, we create a throw-away r
 5025              // type, create a dot-suffix expression around this receiver, and then resolve it in the usual way for dot
 05026              var lhs = new ImplicitThisExpr_ConstructorCall(initCallTok) { Type = rr.EType };
 05027              var callLhs = new ExprDotName(((UserDefinedType)rr.EType).tok, lhs, initCallName, ret == null ? null : ret
 05028              ResolveDotSuffix(callLhs, true, rr.Bindings.ArgumentBindings, resolutionContext, true);
 05029              if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05030                Contract.Assert(callLhs.ResolvedExpression is MemberSelectExpr);  // since ResolveApplySuffix succeeded 
 05031                var methodSel = (MemberSelectExpr)callLhs.ResolvedExpression;
 05032                if (methodSel.Member is Method) {
 05033                  rr.InitCall = new CallStmt(stmt.RangeToken, new List<Expression>(), methodSel, rr.Bindings.ArgumentBin
 05034                  ResolveCallStmt(rr.InitCall, resolutionContext, rr.EType);
 05035                  if (rr.InitCall.Method is Constructor) {
 05036                    callsConstructor = true;
 05037                  }
 05038                } else {
 05039                  reporter.Error(MessageSource.Resolver, initCallTok, "object initialization must denote an initializing
 05040                }
 05041              }
 05042            }
 05043          }
 05044          if (rr.EType.IsRefType) {
 05045            var udt = rr.EType.NormalizeExpand() as UserDefinedType;
 05046            if (udt != null) {
 05047              var cl = (ClassDecl)udt.ResolvedClass;  // cast is guaranteed by the call to rr.EType.IsRefType above, tog
 05048              if (!callsConstructor && !cl.IsObjectTrait && !udt.IsArrayType && (cl.HasConstructor || cl.EnclosingModule
 05049                reporter.Error(MessageSource.Resolver, stmt, "when allocating an object of {1}type '{0}', one of its con
 05050                  cl.HasConstructor ? "" : "imported ");
 05051              }
 05052            }
 05053          }
 05054          rr.Type = rr.EType;
 05055        }
 05056      }
 05057      return rr.Type;
 05058    }
 5059
 5060    /// <summary>
 5061    /// Resolve "memberName" in what currently is known as "receiverType". If "receiverType" is an unresolved
 5062    /// proxy type, try to solve enough type constraints and use heuristics to figure out which type contains
 5063    /// "memberName" and return that enclosing type as "tentativeReceiverType". However, try not to make
 5064    /// type-inference decisions about "receiverType"; instead, lay down the further constraints that need to
 5065    /// be satisfied in order for "tentativeReceiverType" to be where "memberName" is found.
 5066    /// Consequently, if "memberName" is found and returned as a "MemberDecl", it may still be the case that
 5067    /// "receiverType" is an unresolved proxy type and that, after solving more type constraints, "receiverType"
 5068    /// eventually gets set to a type more specific than "tentativeReceiverType".
 5069    /// </summary>
 84605070    public MemberDecl ResolveMember(IToken tok, Type receiverType, string memberName, out NonProxyType tentativeReceiver
 5071      Contract.Requires(tok != null);
 5072      Contract.Requires(receiverType != null);
 5073      Contract.Requires(memberName != null);
 5074      Contract.Ensures(Contract.Result<MemberDecl>() == null || Contract.ValueAtReturn(out tentativeReceiverType) != nul
 5075
 84605076      receiverType = PartiallyResolveTypeForMemberSelection(tok, receiverType, memberName);
 5077
 84605078      if (receiverType is TypeProxy) {
 05079        reporter.Error(MessageSource.Resolver, tok, "type of the receiver is not fully determined at this program point"
 05080        tentativeReceiverType = null;
 05081        return null;
 5082      }
 84605083      Contract.Assert(receiverType is NonProxyType);  // there are only two kinds of types: proxies and non-proxies
 5084
 2030405085      foreach (var valuet in valuetypeDecls) {
 592205086        if (valuet.IsThisType(receiverType)) {
 05087          if (valuet.Members.TryGetValue(memberName, out var member)) {
 05088            SelfType resultType = null;
 05089            if (member is SpecialFunction) {
 05090              resultType = ((SpecialFunction)member).ResultType as SelfType;
 05091            } else if (member is SpecialField) {
 05092              resultType = ((SpecialField)member).Type as SelfType;
 05093            }
 05094            if (resultType != null) {
 05095              SelfTypeSubstitution = new Dictionary<TypeParameter, Type>();
 05096              SelfTypeSubstitution.Add(resultType.TypeArg, receiverType);
 05097              resultType.ResolvedType = receiverType;
 05098            }
 05099            tentativeReceiverType = (NonProxyType)receiverType;
 05100            return member;
 5101          }
 05102          break;
 5103        }
 592205104      }
 5105
 84605106      var ctype = receiverType.NormalizeExpand() as UserDefinedType;
 84605107      var cd = ctype?.AsTopLevelTypeWithMembersBypassInternalSynonym;
 169205108      if (cd != null) {
 84605109        Contract.Assert(ctype.TypeArgs.Count == cd.TypeArgs.Count);  // follows from the fact that ctype was resolved
 84605110        if (!classMembers[cd].TryGetValue(memberName, out var member)) {
 05111          if (memberName == "_ctor") {
 05112            reporter.Error(MessageSource.Resolver, tok, "{0} {1} does not have an anonymous constructor", cd.WhatKind, c
 05113          } else {
 05114            reporter.Error(MessageSource.Resolver, tok, "member '{0}' does not exist in {2} '{1}'", memberName, cd.Name,
 05115          }
 84605116        } else if (!VisibleInScope(member)) {
 05117          reporter.Error(MessageSource.Resolver, tok, "member '{0}' has not been imported in this scope and cannot be ac
 84605118        } else {
 84605119          tentativeReceiverType = ctype;
 84605120          return member;
 5121        }
 05122        tentativeReceiverType = null;
 05123        return null;
 5124      }
 5125
 05126      reporter.Error(MessageSource.Resolver, tok, "type {0} does not have a member {1}", receiverType, memberName);
 05127      tentativeReceiverType = null;
 05128      return null;
 84605129    }
 5130
 5131    /// <summary>
 5132    /// Roughly speaking, tries to figure out the head of the type of "t", making as few inference decisions as possible
 5133    /// More precisely, returns a type that contains all the members of "t"; or if "memberName" is non-null, a type
 5134    /// that at least contains the member "memberName" of "t".  Typically, this type is the head type of "t",
 5135    /// but it may also be a type in a super- or subtype relation to "t".
 5136    /// In some cases, it is necessary to make some inference decisions in order to figure out the type to return.
 5137    /// </summary>
 621905138    public Type PartiallyResolveTypeForMemberSelection(IToken tok, Type t, string memberName = null, int strength = 0) {
 5139      Contract.Requires(tok != null);
 5140      Contract.Requires(t != null);
 5141      Contract.Ensures(Contract.Result<Type>() != null);
 5142      Contract.Ensures(!(Contract.Result<Type>() is TypeProxy) || ((TypeProxy)Contract.Result<Type>()).T == null);
 621905143      t = t.NormalizeExpand();
 775905144      if (!(t is TypeProxy)) {
 154005145        return t;  // we're good
 5146      }
 5147
 5148      // simplify constraints
 467905149      PrintTypeConstraintState(10);
 709305150      if (strength > 0) {
 241405151        var proxySpecializations = new HashSet<TypeProxy>();
 241405152        GetRelatedTypeProxies(t, proxySpecializations);
 241405153        var anyNewConstraintsAssignable = ConvertAssignableToSubtypeConstraints(proxySpecializations);
 241405154        var anyNewConstraintsEquatable = TightenUpEquatable(proxySpecializations);
 360205155        if ((strength > 1 && !anyNewConstraintsAssignable && !anyNewConstraintsEquatable) || strength == 10) {
 237605156          if (t is TypeProxy) {
 5157            // One more try
 118805158            var r = GetBaseTypeFromProxy((TypeProxy)t, new Dictionary<TypeProxy, Type>());
 119705159            if (r != null) {
 905160              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05161                Options.OutputWriter.WriteLine("  ----> found improvement through GetBaseTypeFromProxy: {0}", r);
 05162              }
 905163              return r;
 5164            }
 117905165          }
 5166
 117905167          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05168            Options.OutputWriter.WriteLine("  ----> found no improvement, giving up");
 05169          }
 117905170          return t;
 5171        }
 122605172      }
 349105173      PartiallySolveTypeConstraints(false);
 349105174      PrintTypeConstraintState(11);
 349105175      t = t.NormalizeExpandKeepConstraints();
 349105176      var proxy = t as TypeProxy;
 349205177      if (proxy == null) {
 105178        return t;  // simplification did the trick
 5179      }
 349005180      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05181        Options.OutputWriter.WriteLine("DEBUG: Member selection{3}:  {1} :> {0} :> {2}", t,
 05182          Util.Comma(proxy.SupertypesKeepConstraints, su => su.ToString()),
 05183          Util.Comma(proxy.SubtypesKeepConstraints, su => su.ToString()),
 05184          memberName == null ? "" : " (" + memberName + ")");
 05185      }
 5186
 5187      // Look for a join of head symbols among the proxy's subtypes
 349005188      Type joinType = null;
 433805189      if (JoinOfAllSubtypes(proxy, ref joinType, new HashSet<TypeProxy>()) && joinType != null) {
 84805190        DetermineRootLeaf(joinType, out _, out _, out var headIsRoot, out _);
 148005191        if (joinType.IsDatatype) {
 63205192          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05193            Options.OutputWriter.WriteLine("  ----> join is a datatype: {0}", joinType);
 05194          }
 63205195          ConstrainSubtypeRelation(t, joinType, tok, "Member selection requires a supertype of {0} (got something more l
 63205196          return joinType;
 38705197        } else if (headIsRoot) {
 5198          // we're good to go -- by picking "join" (whose type parameters have been replaced by fresh proxies), we're no
 17105199          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05200            Options.OutputWriter.WriteLine("  ----> improved to {0} through join", joinType);
 05201          }
 17105202          AssignProxyAndHandleItsConstraints(proxy, joinType, true);
 17105203          return proxy.NormalizeExpand();  // we return proxy.T instead of join, in case the assignment gets hijacked
 9005204        } else if (memberName == "_#apply" || memberName == "requires" || memberName == "reads") {
 4505205          var generalArrowType = joinType.AsArrowType;  // go all the way to the base type, to get to the general arrow 
 9005206          if (generalArrowType != null) {
 5207            // pick the supertype "generalArrowType" of "join"
 4505208            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05209              Options.OutputWriter.WriteLine("  ----> improved to {0} through join and function application", generalArr
 05210            }
 4505211            ConstrainSubtypeRelation(generalArrowType, t, tok, "Function application requires a subtype of {0} (got some
 4505212            return generalArrowType;
 5213          }
 05214        } else if (memberName != null) {
 5215          // If "join" has a member called "memberName" and no supertype of "join" does, then we'll pick this join
 05216          if (joinType.IsRefType) {
 05217            var joinExpanded = joinType.NormalizeExpand();  // go all the way to the base type, to get to the class
 05218            if (!joinExpanded.IsObjectQ) {
 05219              var cl = ((UserDefinedType)joinExpanded).ResolvedClass as ClassDecl;
 05220              if (cl != null) {
 5221                // TODO: the following could be improved by also supplying an upper bound of the search (computed as a j
 05222                var plausibleMembers = new HashSet<MemberDecl>();
 05223                FindAllMembers(cl, memberName, plausibleMembers);
 05224                if (plausibleMembers.Count == 1) {
 05225                  var mbr = plausibleMembers.First();
 05226                  if (mbr.EnclosingClass == cl) {
 05227                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05228                      Options.OutputWriter.WriteLine("  ----> improved to {0} through member-selection join", joinType);
 05229                    }
 05230                    var joinRoot = joinType.NormalizeExpand();  // blow passed any constraints
 05231                    ConstrainSubtypeRelation(joinRoot, t, tok, "Member selection requires a subtype of {0} (got somethin
 05232                    return joinType;
 05233                  } else {
 5234                    // pick the supertype "mbr.EnclosingClass" of "cl"
 05235                    Contract.Assert(mbr.EnclosingClass is TraitDecl);  // a proper supertype of a ClassDecl must be a Tr
 05236                    var typeMapping = cl.ParentFormalTypeParametersToActuals;
 05237                    TopLevelDecl td = mbr.EnclosingClass;
 05238                    foreach (var tt in cl.TraitAncestors()) {
 5239                      // If there is a match, the list of Type actuals is unique
 5240                      // (a class cannot inherit both Trait<T1> and Trait<T2> with T1 != T2).
 05241                      if (tt == (TraitDecl)mbr.EnclosingClass) {
 05242                        td = tt;
 05243                      }
 05244                    }
 05245                    List<Type> proxyTypeArgs = td.TypeArgs.ConvertAll(t0 => typeMapping.ContainsKey(t0) ? typeMapping[t0
 05246                    var joinMapping = TypeParameter.SubstitutionMap(cl.TypeArgs, joinType.TypeArgs);
 05247                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.Subst(joinMapping));
 05248                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.AsTypeParameter == null ? t0 : (Type)new InferredT
 05249                    var pickItFromHere = new UserDefinedType(tok, mbr.EnclosingClass.Name, mbr.EnclosingClass, proxyType
 05250                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05251                      Options.OutputWriter.WriteLine("  ----> improved to {0} through join and member lookup", pickItFro
 05252                    }
 05253                    ConstrainSubtypeRelation(pickItFromHere, t, tok, "Member selection requires a subtype of {0} (got so
 05254                    return pickItFromHere;
 5255                  }
 5256                }
 05257              }
 05258            }
 05259          }
 05260        }
 05261        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05262          Options.OutputWriter.WriteLine("  ----> found no improvement, because join does not determine type enough");
 05263        }
 05264      }
 5265
 5266      // Compute the meet of the proxy's supertypes
 264205267      Type meet = null;
 281105268      if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null) {
 5269        // If the meet does have the member, then this looks promising. It could be that the
 5270        // type would get further constrained later to pick some subtype (in particular, a
 5271        // subclass that overrides the member) of this meet. But this is the best we can do
 5272        // now.
 22505273        if (meet is TypeProxy) {
 5605274          if (proxy == meet.Normalize()) {
 5275            // can this really ever happen?
 05276            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05277              Options.OutputWriter.WriteLine("  ----> found no improvement (other than the proxy itself)");
 05278            }
 05279            return t;
 5605280          } else {
 5605281            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05282              Options.OutputWriter.WriteLine("  ----> (merging, then trying to improve further) assigning proxy {0}.T :=
 05283            }
 5605284            Contract.Assert(proxy != meet);
 5605285            proxy.T = meet;
 5605286            Contract.Assert(t.NormalizeExpand() == meet);
 5605287            return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 5288          }
 5289        }
 12605290        if (!(meet is ArtificialType)) {
 1305291          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05292            Options.OutputWriter.WriteLine("  ----> improved to {0} through meet", meet);
 05293          }
 1305294          if (memberName != null) {
 05295            AssignProxyAndHandleItsConstraints(proxy, meet, true);
 05296            return proxy.NormalizeExpand(); // we return proxy.T instead of meet, in case the assignment gets hijacked
 1305297          } else {
 1305298            return meet;
 5299          }
 5300        }
 10005301      }
 5302
 5303      // as a last resort, act on any artificial type nearby the proxy
 257305304      var artificialSuper = proxy.InClusterOfArtificial(AllXConstraints);
 278805305      if (artificialSuper != null) {
 21505306        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05307          Options.OutputWriter.WriteLine("  ----> use artificial supertype: {0}", artificialSuper);
 05308        }
 21505309        return artificialSuper;
 5310      }
 5311
 5312      // we weren't able to do it
 235805313      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05314        Options.OutputWriter.WriteLine("  ----> found no improvement using simple things, trying harder once more");
 05315      }
 235805316      return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 621905317    }
 5318
 121305319    private Type/*?*/ GetBaseTypeFromProxy(TypeProxy proxy, Dictionary<TypeProxy, Type/*?*/> determinedProxies) {
 5320      Contract.Requires(proxy != null);
 5321      Contract.Requires(determinedProxies != null);
 122305322      if (determinedProxies.TryGetValue(proxy, out var t)) {
 5323        // "t" may be null (meaning search for "proxy" is underway or was unsuccessful) or non-null (search for
 5324        // "proxy" has completed successfully), but we return it in either case
 1005325        return t;
 5326      }
 120305327      determinedProxies.Add(proxy, null);  // record that search for "proxy" is underway
 5328      // First, go through subtype constraints, treating each as if it were an equality
 189731705329      foreach (var c in AllTypeConstraints) {
 63124205330        t = GetBaseTypeFromProxy_Eq(proxy, c.Super, c.Sub, determinedProxies);
 63126005331        if (t != null) {
 1805332          determinedProxies[proxy] = t;
 1805333          return t;
 5334        }
 63122405335      }
 5336      // Next, check XConstraints that can be seen as equality constraints
 304549005337      foreach (var xc in AllXConstraints) {
 101398005338        switch (xc.ConstraintName) {
 5339          case "Assignable":
 5340          case "Equatable":
 5341          case "EquatableArg":
 95960205342            t = GetBaseTypeFromProxy_Eq(proxy, xc.Types[0], xc.Types[1], determinedProxies);
 95960705343            if (t != null) {
 505344              determinedProxies[proxy] = t;
 505345              return t;
 5346            }
 95959705347            break;
 5348          case "InSet":
 5349            // etc. TODO
 05350            break;
 5351          default:
 5437805352            break;
 5353        }
 101397505354      }
 118005355      return null;
 121305356    }
 5357    /// <summary>
 5358    /// Tries to find a non-proxy type corresponding to "proxy", under the assumption that "t" equals "u" and
 5359    /// "determinedProxies" assumptions.  In the process, may add to "determinedProxies".
 5360    /// </summary>
 159084405361    private Type/*?*/ GetBaseTypeFromProxy_Eq(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> determin
 5362      Contract.Requires(proxy != null);
 5363      Contract.Requires(determinedProxies != null);
 5364      Contract.Requires(t != null);
 5365      Contract.Requires(u != null);
 159084405366      t = t.NormalizeExpand();
 159084405367      u = u.NormalizeExpand();
 159084405368      return GetBaseTypeFromProxy_EqAux(proxy, t, u, determinedProxies) ?? GetBaseTypeFromProxy_EqAux(proxy, u, t, deter
 159084405369    }
 318167505370    private Type/*?*/ GetBaseTypeFromProxy_EqAux(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> deter
 5371      Contract.Requires(proxy != null);
 5372      Contract.Requires(determinedProxies != null);
 5373      Contract.Requires(t != null && (!(t is TypeProxy) || ((TypeProxy)t).T == null));
 5374      Contract.Requires(u != null && (!(u is TypeProxy) || ((TypeProxy)u).T == null));
 318170905375      if (t == proxy) {
 5905376        if (u is TypeProxy) {
 2505377          return GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 905378        } else {
 905379          return u;
 5380        }
 318164105381      } else if (t.ContainsProxy(proxy)) {
 05382        if (u is TypeProxy) {
 05383          u = GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 05384          if (u == null) {
 05385            return null;
 5386          }
 05387        }
 05388        if (Type.SameHead(t, u)) {
 05389          Contract.Assert(t.TypeArgs.Count == u.TypeArgs.Count);
 05390          for (int i = 0; i < t.TypeArgs.Count; i++) {
 05391            var r = GetBaseTypeFromProxy_Eq(proxy, t.TypeArgs[i], u.TypeArgs[i], determinedProxies);
 05392            if (r != null) {
 05393              return r;
 5394            }
 05395          }
 05396        }
 05397      }
 318164105398      return null;
 318167505399    }
 5400
 251605401    private void GetRelatedTypeProxies(Type t, ISet<TypeProxy> proxies) {
 5402      Contract.Requires(t != null);
 5403      Contract.Requires(proxies != null);
 251605404      var proxy = t.Normalize() as TypeProxy;
 254405405      if (proxy == null || proxies.Contains(proxy)) {
 2805406        return;
 5407      }
 248805408      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05409        Options.OutputWriter.WriteLine("DEBUG: GetRelatedTypeProxies: finding {0} interesting", proxy);
 05410      }
 248805411      proxies.Add(proxy);
 5412      // close over interesting constraints
 394695605413      foreach (var c in AllTypeConstraints) {
 131316405414        var super = c.Super.Normalize();
 164588005415        if (super.TypeArgs.Exists(ta => ta.Normalize() == proxy)) {
 05416          GetRelatedTypeProxies(c.Sub, proxies);
 05417        }
 131316405418      }
 639108005419      foreach (var xc in AllXConstraints) {
 212787205420        var xc0 = xc.Types[0].Normalize();
 214775105421        if (xc.ConstraintName == "Assignable" && (xc0 == proxy || xc0.TypeArgs.Exists(ta => ta.Normalize() == proxy))) {
 10205422          GetRelatedTypeProxies(xc.Types[1], proxies);
 212787205423        } else if (xc.ConstraintName == "Innable" && xc.Types[1].Normalize() == proxy) {
 05424          GetRelatedTypeProxies(xc.Types[0], proxies);
 212777005425        } else if ((xc.ConstraintName == "ModifiesFrame" || xc.ConstraintName == "ReadsFrame") && xc.Types[1].Normalize(
 05426          GetRelatedTypeProxies(xc.Types[0], proxies);
 05427        }
 212787205428      }
 251605429    }
 5430
 5431    /// <summary>
 5432    /// Attempts to compute the join of "join", "t", and all of "t"'s known subtype( constraint)s.  The join
 5433    /// ignores type parameters.  It is assumed that "join" on entry already includes the join of all proxies
 5434    /// in "visited". The empty join is represented by "null".
 5435    /// The return is "true" if the join exists.
 5436    /// </summary>
 583305437    bool JoinOfAllSubtypes(Type t, ref Type joinType, ISet<TypeProxy> visited) {
 5438      Contract.Requires(t != null);
 5439      Contract.Requires(visited != null);
 5440
 583305441      t = t.NormalizeExpandKeepConstraints();
 5442
 583305443      var proxy = t as TypeProxy;
 1078305444      if (proxy != null) {
 534405445        if (visited.Contains(proxy)) {
 39405446          return true;
 5447        }
 455605448        visited.Add(proxy);
 5449
 1525805450        foreach (var c in proxy.SubtypeConstraints) {
 53005451          var s = c.Sub.NormalizeExpandKeepConstraints();
 53005452          if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05453            return false;
 5454          }
 53005455        }
 889605456        if (joinType == null) {
 5457          // also consider "Assignable" constraints
 1019016605458          foreach (var c in AllXConstraints) {
 339416205459            if (c.ConstraintName == "Assignable" && c.Types[0].Normalize() == proxy) {
 178005460              var s = c.Types[1].NormalizeExpandKeepConstraints();
 178005461              if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05462                return false;
 5463              }
 178005464            }
 339238205465          }
 434005466        }
 455605467        return true;
 5468      }
 5469
 176405470      if (joinType == null) {
 5471        // stick with what we've got
 88105472        joinType = t;
 88105473        return true;
 405474      } else if (Type.IsHeadSupertypeOf(joinType, t)) {
 5475        // stick with what we've got
 205476        return true;
 05477      } else if (Type.IsHeadSupertypeOf(t, joinType)) {
 05478        joinType = Type.HeadWithProxyArgs(t);
 05479        return true;
 05480      } else {
 05481        joinType = Type.Join(joinType, Type.HeadWithProxyArgs(t), builtIns);  // the only way this can succeed is if we 
 05482        Contract.Assert(joinType == null ||
 05483                        joinType.IsObjectQ || joinType.IsObject ||
 05484                        (joinType is UserDefinedType udt && (udt.ResolvedClass is TraitDecl || (udt.ResolvedClass is Non
 05485        return joinType != null;
 5486      }
 583305487    }
 5488
 5489    /// <summary>
 5490    /// Attempts to compute the meet of "meet", all of "t"'s known supertype( constraint)s, and, if "includeT"
 5491    /// and "t" has no supertype( constraint)s, "t".
 5492    /// The meet ignores type parameters. (Really?? --KRML)
 5493    /// It is assumed that "meet" on entry already includes the meet of all proxies
 5494    /// in "visited". The empty meet is represented by "null".
 5495    /// The return is "true" if the meet exists.
 5496    /// </summary>
 303805497    bool MeetOfAllSupertypes(Type t, ref Type meet, ISet<TypeProxy> visited, bool includeT) {
 5498      Contract.Requires(t != null);
 5499      Contract.Requires(visited != null);
 5500
 303805501      t = t.NormalizeExpandKeepConstraints();
 303805502      var proxy = t as TypeProxy;
 594805503      if (proxy != null) {
 300005504        if (visited.Contains(proxy)) {
 9005505          return true;
 5506        }
 282005507        visited.Add(proxy);
 5508
 282005509        var delegatedToOthers = false;
 934105510        foreach (var c in proxy.SupertypeConstraints) {
 30305511          var s = c.Super.NormalizeExpandKeepConstraints();
 30305512          delegatedToOthers = true;
 33105513          if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 2805514            return false;
 5515          }
 27505516        }
 539705517        if (!delegatedToOthers) {
 5518          // also consider "Assignable" constraints
 668578805519          foreach (var c in AllXConstraints) {
 222609005520            if (c.ConstraintName == "Assignable" && c.Types[1].Normalize() == proxy) {
 9305521              var s = c.Types[0].NormalizeExpandKeepConstraints();
 9305522              delegatedToOthers = true;
 11105523              if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 1805524                return false;
 5525              }
 7505526            }
 222597905527          }
 258705528        }
 302205529        if (delegatedToOthers) {
 24805530          return true;
 494305531        } else if (!includeT) {
 241705532          return true;
 19405533        } else if (meet == null || meet.Normalize() == proxy) {
 8505534          meet = proxy;
 8505535          return true;
 2405536        } else {
 2405537          return false;
 5538        }
 5539      }
 5540
 24505541      if (meet == null) {
 11705542        meet = Type.HeadWithProxyArgs(t);
 11705543        return true;
 1305544      } else if (Type.IsHeadSupertypeOf(t, meet)) {
 5545        // stick with what we've got
 205546        return true;
 905547      } else if (Type.IsHeadSupertypeOf(meet, t)) {
 05548        meet = Type.HeadWithProxyArgs(t);
 05549        return true;
 905550      } else {
 905551        meet = Type.Meet(meet, Type.HeadWithProxyArgs(t), builtIns);
 905552        return meet != null;
 5553      }
 303805554    }
 5555
 5556    /// <summary>
 5557    /// Check that the type uses formal type parameters in a way that is agreeable with their variance specifications.
 5558    /// "context == Co" says that "type" is allowed to vary in the positive direction.
 5559    /// "context == Contra" says that "type" is allowed to vary in the negative direction.
 5560    /// "context == Non" says that "type" must not vary at all.
 5561    /// * "lax" says that the context is not strict -- type parameters declared to be strict must not be used in a lax c
 5562    /// </summary>
 12455563    public void CheckVariance(Type type, ICallable enclosingTypeDefinition, TypeParameter.TPVariance context, bool lax) 
 5564      Contract.Requires(type != null);
 5565      Contract.Requires(enclosingTypeDefinition != null);
 5566
 12455567      type = type.Normalize();  // we keep constraints, since subset types have their own type-parameter variance specif
 12455568      if (type is BasicType) {
 5569        // fine
 12455570      } else if (type is MapType) {
 05571        var t = (MapType)type;
 5572        // If its an infinite map, the domain's context is lax
 05573        CheckVariance(t.Domain, enclosingTypeDefinition, context, lax || !t.Finite);
 05574        CheckVariance(t.Range, enclosingTypeDefinition, context, lax);
 12455575      } else if (type is SetType) {
 05576        var t = (SetType)type;
 5577        // If its an infinite set, the argument's context is lax
 05578        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax || !t.Finite);
 12455579      } else if (type is CollectionType) {
 05580        var t = (CollectionType)type;
 05581        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax);
 24905582      } else if (type is UserDefinedType) {
 12455583        var t = (UserDefinedType)type;
 16605584        if (t.ResolvedClass is TypeParameter tp) {
 4155585          if (tp.Variance != TypeParameter.TPVariance.Non && tp.Variance != context) {
 05586            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 4155587          } else if (tp.StrictVariance && lax) {
 5588            string hint;
 05589            if (tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.NonVariant_Strict) {
 05590              hint = string.Format(" (perhaps try declaring '{0}' as '-{0}' or '!{0}')", tp.Name);
 05591            } else {
 05592              Contract.Assert(tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.Covariant_Strict);
 05593              hint = string.Format(" (perhaps try changing the declaration from '+{0}' to '*{0}')", tp.Name);
 05594            }
 05595            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 05596          }
 12455597        } else {
 8305598          var resolvedClass = t.ResolvedClass;
 8305599          Contract.Assert(resolvedClass != null);  // follows from that the given type was successfully resolved
 8305600          Contract.Assert(resolvedClass.TypeArgs.Count == t.TypeArgs.Count);
 8305601          if (lax) {
 5602            // we have to be careful about uses of the type being defined
 05603            var cg = enclosingTypeDefinition.EnclosingModule.CallGraph;
 05604            var t0 = resolvedClass as ICallable;
 05605            if (t0 != null && cg.GetSCCRepresentative(t0) == cg.GetSCCRepresentative(enclosingTypeDefinition)) {
 05606              reporter.Error(MessageSource.Resolver, t.tok, "using the type being defined ('{0}') here would cause a log
 05607            }
 05608          }
 29055609          for (int i = 0; i < t.TypeArgs.Count; i++) {
 4155610            Type p = t.TypeArgs[i];
 4155611            var tpFormal = resolvedClass.TypeArgs[i];
 4155612            CheckVariance(p, enclosingTypeDefinition,
 4155613              context == TypeParameter.TPVariance.Non ? context :
 4155614              context == TypeParameter.TPVariance.Co ? tpFormal.Variance :
 4155615              TypeParameter.Negate(tpFormal.Variance),
 4155616              lax || !tpFormal.StrictVariance);
 4155617          }
 8305618        }
 12455619      } else {
 05620        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 5621      }
 12455622    }
 5623
 5624    /// <summary>
 5625    /// See ConstrainToIntegerType description for the overload above.
 5626    /// </summary>
 186905627    void ConstrainToIntegerType(IToken tok, Type type, bool allowBitVector, TypeConstraint.ErrorMsg errorMsg) {
 5628      Contract.Requires(tok != null);
 5629      Contract.Requires(type != null);
 5630      Contract.Requires(errorMsg != null);
 5631      // We do two constraints: the first can aid in determining types, but allows bit-vectors; the second excludes bit-
 5632      // However, we reuse the error message, so that only one error gets reported.
 186905633      ConstrainSubtypeRelation(new IntVarietiesSupertype(), type, errorMsg);
 191205634      if (!allowBitVector) {
 4305635        AddXConstraint(tok, "IntegerType", type, errorMsg);
 4305636      }
 186905637    }
 5638
 5639    /// <summary>
 5640    /// Attempts to rewrite a datatype update into more primitive operations, after doing the appropriate resolution che
 5641    /// Upon success, returns that rewritten expression and sets "legalSourceConstructors".
 5642    /// Upon some resolution error, return null.
 5643    ///
 5644    /// Actually, the method returns two expressions (or returns "(null, null)"). The first expression is the desugaring
 5645    /// used when the DatatypeUpdateExpr is used in a ghost context. The second is to be used for a compiled context. In
 5646    /// case, "legalSourceConstructors" contains both ghost and compiled constructors.
 5647    ///
 5648    /// The reason for computing both desugarings here is that it's too early to tell if the DatatypeUpdateExpr is being
 5649    /// a ghost or compiled context. This is a consequence of doing the deguaring so early. But it's also convenient to 
 5650    /// desugaring during resolution, because then the desugaring can be constructed as a non-resolved expression on whi
 5651    /// is called--this is easier than constructing an already-resolved expression.
 5652    /// </summary>
 5653    (Expression, Expression) ResolveDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<Tuple<IToken, stri
 05654      ResolutionContext resolutionContext, out List<MemberDecl> members, out List<DatatypeCtor> legalSourceConstructors)
 5655      Contract.Requires(tok != null);
 5656      Contract.Requires(root != null);
 5657      Contract.Requires(dt != null);
 5658      Contract.Requires(memberUpdates != null);
 5659      Contract.Requires(resolutionContext != null);
 5660
 05661      legalSourceConstructors = null;
 05662      members = new List<MemberDecl>();
 5663
 5664      // First, compute the list of candidate result constructors, that is, the constructors
 5665      // that have all of the mentioned destructors. Issue errors for duplicated names and for
 5666      // names that are not destructors in the datatype.
 05667      var candidateResultCtors = dt.Ctors;  // list of constructors that have all the so-far-mentioned destructors
 05668      var memberNames = new HashSet<string>();
 05669      var rhsBindings = new Dictionary<string, Tuple<BoundVar/*let variable*/, IdentifierExpr/*id expr for let variable*
 05670      var subst = TypeParameter.SubstitutionMap(dt.TypeArgs, root.Type.NormalizeExpand().TypeArgs);
 05671      foreach (var entry in memberUpdates) {
 05672        var destructor_str = entry.Item2;
 05673        if (memberNames.Contains(destructor_str)) {
 05674          reporter.Error(MessageSource.Resolver, entry.Item1, "duplicate update member '{0}'", destructor_str);
 05675        } else {
 05676          memberNames.Add(destructor_str);
 05677          if (!classMembers[dt].TryGetValue(destructor_str, out var member)) {
 05678            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' does not exist in datatype '{1}'", destruc
 05679          } else if (!(member is DatatypeDestructor)) {
 05680            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' is not a destructor in datatype '{1}'", de
 05681          } else {
 05682            members.Add(member);
 05683            var destructor = (DatatypeDestructor)member;
 05684            var intersection = new List<DatatypeCtor>(candidateResultCtors.Intersect(destructor.EnclosingCtors));
 05685            if (intersection.Count == 0) {
 05686              reporter.Error(MessageSource.Resolver, entry.Item1,
 05687                "updated datatype members must belong to the same constructor (unlike the previously mentioned destructo
 05688                destructor_str, DatatypeDestructor.PrintableCtorNameList(candidateResultCtors, "or"));
 05689            } else {
 05690              candidateResultCtors = intersection;
 05691              if (destructor.IsGhost) {
 05692                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(null, null, entry.Item3)
 05693              } else {
 05694                var xName = FreshTempVarName(string.Format("dt_update#{0}#", destructor_str), resolutionContext.CodeCont
 05695                var xVar = new BoundVar(new AutoGeneratedToken(tok), xName, destructor.Type.Subst(subst));
 05696                var x = new IdentifierExpr(new AutoGeneratedToken(tok), xVar);
 05697                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(xVar, x, entry.Item3));
 05698              }
 05699            }
 05700          }
 05701        }
 05702      }
 05703      if (candidateResultCtors.Count == 0) {
 05704        return (null, null);
 5705      }
 5706
 5707      // Check that every candidate result constructor has given a name to all of its parameters.
 05708      var hasError = false;
 05709      foreach (var ctor in candidateResultCtors) {
 05710        if (ctor.Formals.Exists(f => !f.HasName)) {
 05711          reporter.Error(MessageSource.Resolver, tok,
 05712            "candidate result constructor '{0}' has an anonymous parameter (to use in datatype update expression, name a
 05713            ctor.Name);
 05714          hasError = true;
 05715        }
 05716      }
 05717      if (hasError) {
 05718        return (null, null);
 5719      }
 5720
 5721      // The legal source constructors are the candidate result constructors. (Yep, two names for the same thing.)
 05722      legalSourceConstructors = candidateResultCtors;
 05723      Contract.Assert(1 <= legalSourceConstructors.Count);
 5724
 05725      var desugaringForGhostContext = DesugarDatatypeUpdate(tok, root, dt, candidateResultCtors, rhsBindings, resolution
 05726      var nonGhostConstructors = candidateResultCtors.Where(ctor => !ctor.IsGhost).ToList();
 05727      if (nonGhostConstructors.Count == candidateResultCtors.Count) {
 05728        return (desugaringForGhostContext, desugaringForGhostContext);
 5729      }
 05730      var desugaringForCompiledContext = DesugarDatatypeUpdate(tok, root, dt, nonGhostConstructors, rhsBindings, resolut
 05731      return (desugaringForGhostContext, desugaringForCompiledContext);
 05732    }
 5733
 5734    /// <summary>
 5735    // Rewrite the datatype update root.(x := X, y := Y, ...) to:
 5736    ///     var d := root;
 5737    ///     var x := X;  // EXCEPT: don't do this for ghost fields
 5738    ///     var y := Y;
 5739    ///     ..
 5740    ///     if d.CandidateResultConstructor0 then
 5741    ///       CandidateResultConstructor0(x, y, ..., d.f0, d.f1, ...)  // for a ghost field x, use the expression X dire
 5742    ///     else if d.CandidateResultConstructor1 then
 5743    ///       CandidateResultConstructor0(x, y, ..., d.g0, d.g1, ...)
 5744    ///     ...
 5745    ///     else
 5746    ///       CandidateResultConstructorN(x, y, ..., d.k0, d.k1, ...)
 5747    /// </summary>
 5748    private Expression DesugarDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<DatatypeCtor> candidateR
 05749      Dictionary<string, Tuple<BoundVar, IdentifierExpr, Expression>> rhsBindings, ResolutionContext resolutionContext) 
 5750
 05751      if (candidateResultCtors.Count == 0) {
 05752        return root;
 5753      }
 05754      Expression rewrite = null;
 5755      // Create a unique name for d', the variable we introduce in the let expression
 05756      var dName = FreshTempVarName("dt_update_tmp#", resolutionContext.CodeContext);
 05757      var dVar = new BoundVar(new AutoGeneratedToken(tok), dName, root.Type);
 05758      var d = new IdentifierExpr(new AutoGeneratedToken(tok), dVar);
 05759      Expression body = null;
 05760      candidateResultCtors.Reverse();
 05761      foreach (var crc in candidateResultCtors) {
 5762        // Build the arguments to the datatype constructor, using the updated value in the appropriate slot
 05763        var ctorArguments = new List<Expression>();
 05764        var actualBindings = new List<ActualBinding>();
 05765        foreach (var f in crc.Formals) {
 5766          Expression ctorArg;
 05767          if (rhsBindings.TryGetValue(f.Name, out var info)) {
 05768            ctorArg = info.Item2 ?? info.Item3;
 05769          } else {
 05770            ctorArg = new ExprDotName(tok, d, f.Name, null);
 05771          }
 05772          ctorArguments.Add(ctorArg);
 05773          var bindingName = new Token(tok.line, tok.col) {
 05774            Uri = tok.Uri,
 05775            val = f.Name
 05776          };
 05777          actualBindings.Add(new ActualBinding(bindingName, ctorArg));
 05778        }
 05779        var ctor_call = new DatatypeValue(tok, crc.EnclosingDatatype.Name, crc.Name, actualBindings);
 5780        // in the following line, resolve to root.Type, so that type parameters get filled in appropriately
 05781        ResolveDatatypeValue(resolutionContext, ctor_call, dt, root.Type.NormalizeExpand());
 5782
 05783        if (body == null) {
 05784          body = ctor_call;
 05785        } else {
 5786          // body = if d.crc? then ctor_call else body
 05787          var guard = new ExprDotName(tok, d, crc.QueryField.Name, null);
 05788          body = new ITEExpr(tok, false, guard, ctor_call, body);
 05789        }
 05790      }
 05791      Contract.Assert(body != null); // because there was at least one element in candidateResultCtors
 5792
 5793      // Wrap the let's around body
 05794      rewrite = body;
 05795      foreach (var entry in rhsBindings) {
 05796        if (entry.Value.Item1 != null) {
 05797          var lhs = new CasePattern<BoundVar>(tok, entry.Value.Item1);
 05798          rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { entry.Value.Ite
 05799        }
 05800      }
 05801      var dVarPat = new CasePattern<BoundVar>(tok, dVar);
 05802      rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { dVarPat }, new List<Expression>() { root }, rewrite
 05803      Contract.Assert(rewrite != null);
 05804      ResolveExpression(rewrite, resolutionContext);
 05805      return rewrite;
 05806    }
 5807
 5808    public Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args,
 7791055809      ResolutionContext resolutionContext, bool allowMethodCall, bool complain = true) {
 7791055810      return ResolveNameSegment(expr, isLastNameSegment, args, resolutionContext, allowMethodCall, complain, out _);
 7791055811    }
 5812
 5813    /// <summary>
 5814    /// Look up expr.Name in the following order:
 5815    ///  0. Local variable, parameter, or bound variable.
 5816    ///     (Language design note:  If this clashes with something of interest, one can always rename the local variable
 5817    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 5818    ///  2. If isLastNameSegment:
 5819    ///     Unambiguous constructor name of a datatype in the enclosing module (if two constructors have the same name, 
 5820    ///     (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority, on
 5821    ///  3. Member of the enclosing module (type name or the name of a module)
 5822    ///  4. Static function or method in the enclosing module or its imports
 5823    ///  5. If !isLastNameSegment:
 5824    ///     Unambiguous constructor name of a datatype in the enclosing module
 5825    ///
 5826    /// </summary>
 5827    /// <param name="expr"></param>
 5828    /// <param name="isLastNameSegment">Indicates that the NameSegment is not directly enclosed in another NameSegment o
 5829    /// <param name="args">If the NameSegment is enclosed in an ApplySuffix, then these are the arguments.  The method r
 5830    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 5831    /// that incorporates these arguments.</param>
 5832    /// <param name="resolutionContext"></param>
 5833    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 5834    /// a MemberSelectExpr whose .Member is a Method.</param>
 5835    /// <param name="shadowedModule">If the name being resolved shadows an imported module, then that module is reported
 5836    /// through this parameter.  This happens when module <c>Option</c> in <c>import opened Option</c> also contains a
 5837    /// <c>datatype Option</c>, in which case <c>Option</c> refers to the datatype, not the module
 5838    /// (https://github.com/dafny-lang/dafny/issues/1996).</param>
 7844155839    Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext 
 5840      Contract.Requires(expr != null);
 5841      Contract.Requires(!expr.WasResolved());
 5842      Contract.Requires(resolutionContext != null);
 5843      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 5844
 7844155845      shadowedModule = null;
 5846
 7844155847      if (expr.OptTypeArguments != null) {
 05848        foreach (var ty in expr.OptTypeArguments) {
 05849          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 05850        }
 05851      }
 5852
 7844155853      Expression r = null;  // the resolved expression, if successful
 7844155854      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 5855
 5856      // For 0:
 5857      IVariable v;
 5858      // For 1:
 5859      // For 1 and 4:
 7844155860      MemberDecl member = null;
 5861      // For 2 and 5:
 5862      // For 3:
 5863
 7844155864      var name = resolutionContext.InReveal ? "reveal_" + expr.Name : expr.Name;
 7844155865      v = scope.Find(name);
 15470405866      if (v != null) {
 5867        // ----- 0. local variable, parameter, or bound variable
 7626255868        if (expr.OptTypeArguments != null) {
 05869          if (complain) {
 05870            reporter.Error(MessageSource.Resolver, expr.tok, "variable '{0}' does not take any type parameters", name);
 05871          } else {
 05872            expr.ResolvedExpression = null;
 05873            return null;
 5874          }
 05875        }
 7626255876        r = new IdentifierExpr(expr.tok, v);
 8062055877      } else if (currentClass is TopLevelDeclWithMembers cl && classMembers.TryGetValue(cl, out var members) && members.
 5878        // ----- 1. member of the enclosing class
 5879        Expression receiver;
 435805880        if (member.IsStatic) {
 217905881          receiver = new StaticReceiverExpr(expr.tok, UserDefinedType.FromTopLevelDecl(expr.tok, currentClass, currentCl
 217905882        } else {
 05883          if (!scope.AllowInstance) {
 05884            if (complain) {
 05885              reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context"); //TODO: R
 05886            } else {
 05887              expr.ResolvedExpression = null;
 05888              return null;
 5889            }
 5890            // nevertheless, set "receiver" to a value so we can continue resolution
 05891          }
 05892          receiver = new ImplicitThisExpr(expr.tok);
 05893          receiver.Type = GetThisType(expr.tok, currentClass);  // resolve here
 05894        }
 217905895        r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allowMe
 217905896      } else if (isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out var pair)) {
 5897        // ----- 2. datatype constructor
 05898        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05899          return null;
 5900        }
 05901      } else if (moduleInfo.TopLevels.TryGetValue(name, out var decl)) {
 5902        // ----- 3. Member of the enclosing module
 5903
 5904        // Record which imported module, if any, was shadowed by `name` in the current module.
 05905        shadowedModule = moduleInfo.ShadowedImportedModules.GetValueOrDefault(name);
 5906
 05907        if (decl is AmbiguousTopLevelDecl) {
 05908          var ad = (AmbiguousTopLevelDecl)decl;
 05909          if (complain) {
 05910            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 05911          } else {
 05912            expr.ResolvedExpression = null;
 05913            return null;
 5914          }
 05915        } else {
 5916          // We have found a module name or a type name, neither of which is an expression. However, the NameSegment we'
 5917          // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of t
 5918          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 5919          // or verifier, just to have a placeholder where we can recorded what we have found.
 05920          if (!isLastNameSegment) {
 05921            if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 5922              // A possibly-null type C? was mentioned. But it does not have any further members. The program should hav
 5923              // the name of the class, C. Report an error and continue.
 05924              if (complain) {
 05925                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 05926              } else {
 05927                expr.ResolvedExpression = null;
 05928                return null;
 5929              }
 05930            }
 05931          }
 05932          r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 05933        }
 5934
 05935      } else if (moduleInfo.StaticMembers.TryGetValue(name, out member)) {
 5936        // ----- 4. static member of the enclosing module
 05937        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 05938        if (member is AmbiguousMemberDecl) {
 05939          var ambiguousMember = (AmbiguousMemberDecl)member;
 05940          if (complain) {
 05941            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 05942          } else {
 05943            expr.ResolvedExpression = null;
 05944            return null;
 5945          }
 05946        } else {
 05947          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass, true);
 05948          r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allow
 05949        }
 5950
 05951      } else if (!isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out pair)) {
 5952        // ----- 5. datatype constructor
 05953        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05954          return null;
 5955        }
 5956
 05957      } else {
 5958        // ----- None of the above
 05959        if (complain) {
 05960          if (resolutionContext.InReveal) {
 05961            reporter.Error(MessageSource.Resolver, expr.tok, "cannot reveal '{0}' because no constant, assert label, or 
 05962          } else {
 05963            reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 05964          }
 05965        } else {
 05966          expr.ResolvedExpression = null;
 05967          return null;
 5968        }
 05969      }
 5970
 7844155971      if (r == null) {
 5972        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 05973        expr.Type = new InferredTypeProxy();
 7844155974      } else {
 7844155975        expr.ResolvedExpression = r;
 7844155976        var rt = r.Type;
 7844155977        var nt = rt.UseInternalSynonym();
 7844155978        expr.Type = nt;
 7844155979      }
 7844155980      return rWithArgs;
 7844155981    }
 5982
 05983    private bool ResolveDatatypeConstructor(NameSegment expr, List<ActualBinding>/*?*/ args, ResolutionContext resolutio
 5984      Contract.Requires(expr != null);
 5985      Contract.Requires(resolutionContext != null);
 5986
 05987      if (pair.Item2) {
 5988        // there is more than one constructor with this name
 05989        if (complain) {
 05990          reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor, but does not 
 05991            pair.Item1.EnclosingDatatype.Name);
 05992        } else {
 05993          expr.ResolvedExpression = null;
 05994          return true;
 5995        }
 05996      } else {
 05997        if (expr.OptTypeArguments != null) {
 05998          if (complain) {
 05999            reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters ('{
 06000          } else {
 06001            expr.ResolvedExpression = null;
 06002            return true;
 6003          }
 06004        }
 06005        var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>())
 06006        bool ok = ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null, complain);
 06007        if (!ok) {
 06008          expr.ResolvedExpression = null;
 06009          return true;
 6010        }
 06011        if (args == null) {
 06012          r = rr;
 06013        } else {
 06014          r = rr; // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been proper to 
 06015          rWithArgs = rr;
 06016        }
 06017      }
 06018      return false;
 06019    }
 6020
 6021    /// <summary>
 6022    /// Look up expr.Name in the following order:
 6023    ///  0. Type parameter
 6024    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 6025    ///  2. Member of the enclosing module (type name or the name of a module)
 6026    ///  3. Static function or method in the enclosing module or its imports
 6027    ///
 6028    /// Note: 1 and 3 are not used now, but they will be of interest when async task types are supported.
 6029    /// </summary>
 1249106030    void ResolveNameSegment_Type(NameSegment expr, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 6031      Contract.Requires(expr != null);
 6032      Contract.Requires(!expr.WasResolved());
 6033      Contract.Requires(resolutionContext != null);
 6034      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6035
 1510356036      if (expr.OptTypeArguments != null) {
 2741106037        foreach (var ty in expr.OptTypeArguments) {
 652456038          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 652456039        }
 261256040      }
 6041
 1249106042      Expression r = null;  // the resolved expression, if successful
 6043
 6044      // For 0:
 6045      TypeParameter tp;
 6046#if ASYNC_TASK_TYPES
 6047      // For 1:
 6048      Dictionary<string, MemberDecl> members;
 6049      // For 1 and 3:
 6050      MemberDecl member = null;
 6051#endif
 6052      // For 2:
 6053
 1249106054      tp = allTypeParameters.Find(expr.Name);
 1415106055      if (tp != null) {
 6056        // ----- 0. type parameter
 332006057        if (expr.OptTypeArguments == null) {
 166006058          r = new Resolver_IdentifierExpr(expr.tok, tp);
 166006059        } else {
 06060          reporter.Error(MessageSource.Resolver, expr.tok, "Type parameter expects no type arguments: {0}", expr.Name);
 06061        }
 6062#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6063      } else if (currentClass != null && classMembers.TryGetValue(currentClass, out members) && members.TryGetValue(expr
 6064        // ----- 1. member of the enclosing class
 6065        Expression receiver;
 6066        if (member.IsStatic) {
 6067          receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6068        } else {
 6069          if (!scope.AllowInstance) {
 6070            reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context");
 6071            // nevertheless, set "receiver" to a value so we can continue resolution
 6072          }
 6073          receiver = new ImplicitThisExpr(expr.tok);
 6074          receiver.Type = GetThisType(expr.tok, (ClassDecl)member.EnclosingClass);  // resolve here
 6075        }
 6076        r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodCal
 6077#endif
 2332206078      } else if (moduleInfo.TopLevels.TryGetValue(expr.Name, out var decl)) {
 6079        // ----- 2. Member of the enclosing module
 1083106080        if (decl is AmbiguousTopLevelDecl) {
 06081          var ad = (AmbiguousTopLevelDecl)decl;
 06082          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 1083106083        } else {
 6084          // We have found a module name or a type name, neither of which is a type expression. However, the NameSegment
 6085          // looking at may be followed by a further suffix that makes this into a type expresion. We postpone the rest 
 6086          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 6087          // or verifier, just to have a placeholder where we can recorded what we have found.
 1083106088          r = CreateResolver_IdentifierExpr(expr.tok, expr.Name, expr.OptTypeArguments, decl);
 1083106089        }
 6090
 6091#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6092      } else if (moduleInfo.StaticMembers.TryGetValue(expr.Name, out member)) {
 6093        // ----- 3. static member of the enclosing module
 6094        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 6095        if (ReallyAmbiguousThing(ref member)) {
 6096          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one of
 6097        } else {
 6098          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6099          r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodC
 6100        }
 6101#endif
 1083106102      } else {
 6103        // ----- None of the above
 06104        reporter.Error(MessageSource.Resolver, expr.tok, "Type or type parameter is not declared in this scope: {0} (did
 06105      }
 6106
 1249106107      if (r == null) {
 6108        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06109        expr.Type = new InferredTypeProxy();
 1249106110      } else {
 1249106111        expr.ResolvedExpression = r;
 1249106112        expr.Type = r.Type;
 1249106113      }
 1249106114    }
 6115
 6116    /// <summary>
 6117    /// To resolve "id" in expression "E . id", do:
 6118    ///  * If E denotes a module name M:
 6119    ///      0. If isLastNameSegment:
 6120    ///         Unambiguous constructor name of a datatype in module M (if two constructors have the same name, an error
 6121    ///         (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority
 6122    ///      1. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 6123    ///         (if two imported types have the same name, an error message is produced here)
 6124    ///      2. Static function or method of M._default
 6125    ///    (Note that in contrast to ResolveNameSegment, imported modules, etc. are ignored)
 6126    ///  * If E denotes a type:
 6127    ///      3. Look up id as a member of that type
 6128    ///  * If E denotes an expression:
 6129    ///      4. Let T be the type of E.  Look up id in T.
 6130    /// </summary>
 6131    /// <param name="expr"></param>
 6132    /// <param name="isLastNameSegment">Indicates that the ExprDotName is not directly enclosed in another ExprDotName e
 6133    /// <param name="args">If the ExprDotName is enclosed in an ApplySuffix, then these are the arguments.  The method r
 6134    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 6135    /// that incorporates these arguments.</param>
 6136    /// <param name="resolutionContext"></param>
 6137    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 6138    /// a Resolver_MethodCall.</param>
 84606139    Expression ResolveDotSuffix(ExprDotName expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext re
 6140      Contract.Requires(expr != null);
 6141      Contract.Requires(!expr.WasResolved());
 6142      Contract.Requires(resolutionContext != null);
 6143      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 6144
 6145      // resolve the LHS expression
 6146      // LHS should not be reveal lemma
 84606147      ModuleDecl shadowedImport = null;
 84606148      ResolutionContext nonRevealOpts = resolutionContext with { InReveal = false };
 137706149      if (expr.Lhs is NameSegment) {
 53106150        ResolveNameSegment((NameSegment)expr.Lhs, false, null, nonRevealOpts, false, true, out shadowedImport);
 94306151      } else if (expr.Lhs is ExprDotName) {
 9706152        ResolveDotSuffix((ExprDotName)expr.Lhs, false, null, nonRevealOpts, false);
 31506153      } else {
 21806154        ResolveExpression(expr.Lhs, nonRevealOpts);
 21806155      }
 6156
 84606157      if (expr.OptTypeArguments != null) {
 06158        foreach (var ty in expr.OptTypeArguments) {
 06159          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 06160        }
 06161      }
 6162
 84606163      Expression r = null;  // the resolved expression, if successful
 84606164      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 84606165      MemberDecl member = null;
 6166
 84606167      var name = resolutionContext.InReveal ? "reveal_" + expr.SuffixName : expr.SuffixName;
 84606168      if (!expr.Lhs.WasResolved()) {
 06169        return null;
 6170      }
 84606171      var lhs = expr.Lhs.Resolved;
 84606172      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06173        var ri = (Resolver_IdentifierExpr)lhs;
 06174        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 06175        sig = GetSignature(sig);
 6176        // For 0:
 6177        // For 1:
 6178
 06179        if (isLastNameSegment && sig.Ctors.TryGetValue(name, out var pair)) {
 6180          // ----- 0. datatype constructor
 06181          if (pair.Item2) {
 6182            // there is more than one constructor with this name
 06183            reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor in module {2
 06184          } else {
 06185            if (expr.OptTypeArguments != null) {
 06186              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06187            }
 06188            var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding
 06189            ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null);
 6190
 06191            if (args == null) {
 06192              r = rr;
 06193            } else {
 06194              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06195              rWithArgs = rr;
 06196            }
 06197          }
 06198        } else if (sig.TopLevels.TryGetValue(name, out var decl)) {
 6199          // ----- 1. Member of the specified module
 06200          if (decl is AmbiguousTopLevelDecl) {
 06201            var ad = (AmbiguousTopLevelDecl)decl;
 06202            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 06203          } else {
 6204            // We have found a module name or a type name, neither of which is an expression. However, the ExprDotName w
 6205            // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of
 6206            // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the c
 6207            // or verifier, just to have a placeholder where we can recorded what we have found.
 06208            if (!isLastNameSegment) {
 06209              if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 6210                // A possibly-null type C? was mentioned. But it does not have any further members. The program should h
 6211                // the name of the class, C. Report an error and continue.
 06212                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 06213              }
 06214            }
 06215            r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 06216          }
 06217        } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 6218          // ----- 2. static member of the specified module
 06219          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 06220          if (member is AmbiguousMemberDecl) {
 06221            var ambiguousMember = (AmbiguousMemberDecl)member;
 06222            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 06223          } else {
 06224            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (ClassDecl)member.EnclosingClass, false);
 06225            receiver.ContainerExpression = expr.Lhs;
 06226            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06227          }
 06228        } else {
 06229          reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 06230        }
 6231
 84606232      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 06233        var ri = (Resolver_IdentifierExpr)lhs;
 6234        // ----- 3. Look up name in type
 6235        // expand any synonyms
 06236        var ty = new UserDefinedType(expr.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs).NormalizeExpand();
 06237        if (ty.IsDatatype) {
 6238          // ----- LHS is a datatype
 06239          var dt = ty.AsDatatype;
 06240          if (dt.ConstructorsByName != null && dt.ConstructorsByName.TryGetValue(name, out var ctor)) {
 06241            if (expr.OptTypeArguments != null) {
 06242              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06243            }
 06244            var rr = new DatatypeValue(expr.tok, ctor.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>());
 06245            ResolveDatatypeValue(resolutionContext, rr, ctor.EnclosingDatatype, ty);
 06246            if (args == null) {
 06247              r = rr;
 06248            } else {
 06249              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06250              rWithArgs = rr;
 06251            }
 06252          }
 06253        }
 06254        var cd = r == null ? ty.AsTopLevelTypeWithMembersBypassInternalSynonym : null;
 06255        if (cd != null) {
 6256          // ----- LHS is a type with members
 06257          if (classMembers.TryGetValue(cd, out var members) && members.TryGetValue(name, out member)) {
 06258            if (!VisibleInScope(member)) {
 06259              reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' has not been imported in this scope and can
 06260            }
 06261            if (!member.IsStatic) {
 06262              reporter.Error(MessageSource.Resolver, expr.tok, "accessing member '{0}' requires an instance expression",
 6263              // nevertheless, continue creating an expression that approximates a correct one
 06264            }
 06265            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (UserDefinedType)ty.NormalizeExpand(), (TopLevelDeclWith
 06266            receiver.ContainerExpression = expr.Lhs;
 06267            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06268          }
 06269        }
 06270        if (r == null) {
 06271          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in {2} '{1}'", name, ri.Decl.Nam
 06272        }
 169206273      } else if (lhs != null) {
 6274        // ----- 4. Look up name in the type of the Lhs
 84606275        member = ResolveMember(expr.tok, expr.Lhs.Type, name, out var tentativeReceiverType);
 169206276        if (member != null) {
 6277          Expression receiver;
 169206278          if (!member.IsStatic) {
 84606279            receiver = expr.Lhs;
 84606280            AddAssignableConstraint(expr.tok, tentativeReceiverType, receiver.Type, "receiver type ({1}) does not have a
 84606281            r = ResolveExprDotCall(expr.tok, receiver, tentativeReceiverType, member, args, expr.OptTypeArguments, resol
 84606282          } else {
 06283            receiver = new StaticReceiverExpr(expr.tok, (UserDefinedType)tentativeReceiverType, (TopLevelDeclWithMembers
 06284            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06285          }
 84606286        }
 84606287      }
 6288
 84606289      if (r == null) {
 6290        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06291        expr.Type = new InferredTypeProxy();
 84606292      } else {
 84606293        CheckForAmbiguityInShadowedImportedModule(shadowedImport, name, expr.tok, useCompileSignatures, isLastNameSegmen
 84606294        expr.ResolvedExpression = r;
 84606295        expr.Type = r.Type;
 84606296      }
 84606297      return rWithArgs;
 84606298    }
 6299
 6300    /// <summary>
 6301    /// Check whether the name we just resolved may have been resolved differently if we didn't allow member `M.M` of
 6302    /// module `M` to shadow `M` when the user writes `import opened M`.  Raising an error in that case allowed us to
 6303    /// change the behavior of `import opened` without silently changing the meaning of existing programs.
 6304    /// (https://github.com/dafny-lang/dafny/issues/1996)
 6305    ///
 6306    /// Note the extra care for the constructor case, which is needed because the constructors of datatype `M.M` are
 6307    /// exposed through both `M` and `M.M`, without ambiguity.
 6308    /// </summary>
 6309    private void CheckForAmbiguityInShadowedImportedModule(ModuleDecl moduleDecl, string name,
 84606310      IToken tok, bool useCompileSignatures, bool isLastNameSegment) {
 84606311      if (moduleDecl != null && NameConflictsWithModuleContents(moduleDecl, name, useCompileSignatures, isLastNameSegmen
 06312        reporter.Error(MessageSource.Resolver, tok,
 06313          "Reference to member '{0}' is ambiguous: name '{1}' shadows an import-opened module of the same name, and "
 06314          + "both have a member '{0}'. To solve this issue, give a different name to the imported module using "
 06315          + "`import opened XYZ = ...` instead of `import opened ...`.",
 06316          name, moduleDecl.Name);
 06317      }
 84606318    }
 6319
 06320    private bool NameConflictsWithModuleContents(ModuleDecl moduleDecl, string name, bool useCompileSignatures, bool isL
 06321      var sig = GetSignature(moduleDecl.AccessibleSignature(useCompileSignatures));
 06322      return (
 06323        (isLastNameSegment
 06324         && sig.Ctors.GetValueOrDefault(name) is { Item1: var constructor, Item2: var ambiguous }
 06325         && !ambiguous && constructor.EnclosingDatatype.Name != moduleDecl.Name)
 06326        || sig.TopLevels.ContainsKey(name)
 06327        || sig.StaticMembers.ContainsKey(name)
 06328      );
 06329    }
 6330
 6331    Expression ResolveExprDotCall(IToken tok, Expression receiver, Type receiverTypeBound/*?*/,
 302506332      MemberDecl member, List<ActualBinding> args, List<Type> optTypeArguments, ResolutionContext resolutionContext, boo
 6333      Contract.Requires(tok != null);
 6334      Contract.Requires(receiver != null);
 6335      Contract.Requires(receiver.WasResolved());
 6336      Contract.Requires(member != null);
 6337      Contract.Requires(resolutionContext != null && resolutionContext.CodeContext != null);
 6338
 302506339      var rr = new MemberSelectExpr(tok, receiver, member.Name);
 302506340      rr.Member = member;
 6341
 6342      // Now, fill in rr.Type.  This requires taking into consideration the type parameters passed to the receiver's typ
 6343      // parameters used in this NameSegment/ExprDotName.
 6344      // Add to "subst" the type parameters given to the member's class/datatype
 302506345      rr.TypeApplication_AtEnclosingClass = new List<Type>();
 302506346      rr.TypeApplication_JustMember = new List<Type>();
 6347      Dictionary<TypeParameter, Type> subst;
 302506348      var rType = (receiverTypeBound ?? receiver.Type).NormalizeExpand();
 605006349      if (rType is UserDefinedType udt && udt.ResolvedClass != null) {
 302506350        subst = TypeParameter.SubstitutionMap(udt.ResolvedClass.TypeArgs, udt.TypeArgs);
 302506351        if (member.EnclosingClass == null) {
 6352          // this can happen for some special members, like real.Floor
 302506353        } else {
 302506354          rr.TypeApplication_AtEnclosingClass.AddRange(rType.AsParentType(member.EnclosingClass).TypeArgs);
 302506355        }
 302506356      } else {
 06357        var vtd = AsValuetypeDecl(rType);
 06358        if (vtd != null) {
 06359          Contract.Assert(vtd.TypeArgs.Count == rType.TypeArgs.Count);
 06360          subst = TypeParameter.SubstitutionMap(vtd.TypeArgs, rType.TypeArgs);
 06361          rr.TypeApplication_AtEnclosingClass.AddRange(rType.TypeArgs);
 06362        } else {
 06363          Contract.Assert(rType.TypeArgs.Count == 0);
 06364          subst = new Dictionary<TypeParameter, Type>();
 06365        }
 06366      }
 6367
 387106368      if (member is Field) {
 84606369        var field = (Field)member;
 84606370        if (optTypeArguments != null) {
 06371          reporter.Error(MessageSource.Resolver, tok, "a field ({0}) does not take any type arguments (got {1})", field.
 06372        }
 84606373        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 84606374        rr.Type = field.Type.Subst(subst);
 402506375      } else if (member is Function) {
 100006376        var fn = (Function)member;
 100006377        if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 06378          reporter.Error(MessageSource.Resolver, tok, "two-state function ('{0}') can only be called in a two-state cont
 06379        }
 100006380        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 100006381        if (optTypeArguments != null && suppliedTypeArguments != fn.TypeArgs.Count) {
 06382          reporter.Error(MessageSource.Resolver, tok, "function '{0}' expects {1} type argument{2} (got {3})",
 06383            member.Name, fn.TypeArgs.Count, Util.Plural(fn.TypeArgs.Count), suppliedTypeArguments);
 06384        }
 335906385        for (int i = 0; i < fn.TypeArgs.Count; i++) {
 45306386          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 45306387          rr.TypeApplication_JustMember.Add(ta);
 45306388          subst.Add(fn.TypeArgs[i], ta);
 45306389        }
 100006390        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 100006391        rr.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 217906392      } else {
 6393        // the member is a method
 117906394        var m = (Method)member;
 117906395        if (!allowMethodCall) {
 6396          // it's a method and method calls are not allowed in the given context
 06397          reporter.Error(MessageSource.Resolver, tok, "expression is not allowed to invoke a {0} ({1})", member.WhatKind
 06398        }
 117906399        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 117906400        if (optTypeArguments != null && suppliedTypeArguments != m.TypeArgs.Count) {
 06401          reporter.Error(MessageSource.Resolver, tok, "method '{0}' expects {1} type argument{2} (got {3})",
 06402            member.Name, m.TypeArgs.Count, Util.Plural(m.TypeArgs.Count), suppliedTypeArguments);
 06403        }
 235806404        for (int i = 0; i < m.TypeArgs.Count; i++) {
 06405          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 06406          rr.TypeApplication_JustMember.Add(ta);
 06407          subst.Add(m.TypeArgs[i], ta);
 06408        }
 117906409        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 294706410        rr.ResolvedOutparameterTypes = m.Outs.ConvertAll(f => f.Type.Subst(subst));
 117906411        rr.Type = new InferredTypeProxy();  // fill in this field, in order to make "rr" resolved
 117906412      }
 302506413      return rr;
 302506414    }
 6415
 199106416    public MethodCallInformation ResolveApplySuffix(ApplySuffix e, ResolutionContext resolutionContext, bool allowMethod
 6417      Contract.Requires(e != null);
 6418      Contract.Requires(resolutionContext != null);
 6419      Contract.Ensures(Contract.Result<MethodCallInformation>() == null || allowMethodCall);
 199106420      Expression r = null;  // upon success, the expression to which the ApplySuffix resolves
 199106421      var errorCount = reporter.Count(ErrorLevel.Error);
 390706422      if (e.Lhs is NameSegment) {
 191606423        r = ResolveNameSegment((NameSegment)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall
 6424        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 202306425      } else if (e.Lhs is ExprDotName) {
 3206426        r = ResolveDotSuffix((ExprDotName)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall);
 6427        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 7506428      } else {
 4306429        ResolveExpression(e.Lhs, resolutionContext);
 4306430      }
 199106431      if (e.Lhs.Type == null) {
 6432        // some error had been detected during the attempted resolution of e.Lhs
 06433        e.Lhs.Type = new InferredTypeProxy();
 06434      }
 199106435      Label atLabel = null;
 199106436      if (e.AtTok != null) {
 06437        atLabel = DominatingStatementLabels.Find(e.AtTok.val);
 06438        if (atLabel == null) {
 06439          reporter.Error(MessageSource.Resolver, e.AtTok, "no label '{0}' in scope at this time", e.AtTok.val);
 06440        }
 06441      }
 398206442      if (r == null) {
 199106443        var improvedType = PartiallyResolveTypeForMemberSelection(e.Lhs.tok, e.Lhs.Type, "_#apply");
 199106444        var fnType = improvedType.AsArrowType;
 317006445        if (fnType == null) {
 117906446          var lhs = e.Lhs.Resolved;
 117906447          if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06448            reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a function", ((Resolver_Ident
 117906449          } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 06450            var ri = (Resolver_IdentifierExpr)lhs;
 06451            reporter.Error(MessageSource.Resolver, e.tok, "name of {0} ({1}) is used as a function", ri.Decl.WhatKind, r
 117906452          } else {
 235806453            if (lhs is MemberSelectExpr mse && mse.Member is Method) {
 117906454              if (atLabel != null) {
 06455                Contract.Assert(mse != null); // assured by the parser
 06456                if (mse.Member is TwoStateLemma) {
 06457                  mse.AtLabel = atLabel;
 06458                } else {
 06459                  reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state lemma")
 06460                }
 06461              }
 235806462              if (allowMethodCall) {
 117906463                Contract.Assert(!e.Bindings.WasResolved); // we expect that .Bindings has not yet been processed, so we 
 117906464                var tok = Options.Get(DafnyConsolePrinter.ShowSnippets) ? e.RangeToken.ToToken() : e.tok;
 117906465                var cRhs = new MethodCallInformation(tok, mse, e.Bindings.ArgumentBindings);
 117906466                return cRhs;
 06467              } else {
 06468                reporter.Error(MessageSource.Resolver, e.tok, "{0} call is not allowed to be used in an expression conte
 06469              }
 06470            } else if (lhs != null) {  // if e.Lhs.Resolved is null, then e.Lhs was not successfully resolved and an err
 06471              reporter.Error(MessageSource.Resolver, e.tok, "non-function expression (of type {0}) is called with parame
 06472            }
 06473          }
 6474          // resolve the arguments, even in the presence of the errors above
 06475          foreach (var binding in e.Bindings.ArgumentBindings) {
 06476            ResolveExpression(binding.Actual, resolutionContext);
 06477          }
 81206478        } else {
 81206479          var mse = e.Lhs is NameSegment || e.Lhs is ExprDotName ? e.Lhs.Resolved as MemberSelectExpr : null;
 81206480          var callee = mse == null ? null : mse.Member as Function;
 81206481          if (atLabel != null && !(callee is TwoStateFunction)) {
 06482            reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state function");
 06483            atLabel = null;
 06484          }
 154906485          if (callee != null) {
 6486            // produce a FunctionCallExpr instead of an ApplyExpr(MemberSelectExpr)
 73706487            var rr = new FunctionCallExpr(e.Lhs.tok, callee.Name, mse.Obj, e.tok, e.CloseParen, e.Bindings, atLabel) {
 73706488              Function = callee,
 73706489              TypeApplication_AtEnclosingClass = mse.TypeApplication_AtEnclosingClass,
 73706490              TypeApplication_JustFunction = mse.TypeApplication_JustMember
 73706491            };
 73706492            var typeMap = BuildTypeArgumentSubstitute(mse.TypeArgumentSubstitutionsAtMemberDeclaration());
 73706493            ResolveActualParameters(rr.Bindings, callee.Formals, e.tok, callee, resolutionContext, typeMap, callee.IsSta
 73706494            rr.Type = callee.ResultType.Subst(typeMap);
 147406495            if (errorCount == reporter.Count(ErrorLevel.Error)) {
 73706496              Contract.Assert(!(mse.Obj is StaticReceiverExpr) || callee.IsStatic);  // this should have been checked al
 73706497              Contract.Assert(callee.Formals.Count == rr.Args.Count);  // this should have been checked already
 73706498            }
 73706499            r = rr;
 81206500          } else {
 6501            List<Formal> formals;
 7506502            if (callee != null) {
 06503              formals = callee.Formals;
 7506504            } else {
 7506505              formals = new List<Formal>();
 74406506              for (var i = 0; i < fnType.Args.Count; i++) {
 19806507                var argType = fnType.Args[i];
 19806508                var formal = new ImplicitFormal(e.tok, "_#p" + i, argType, true, false);
 19806509                formals.Add(formal);
 19806510              }
 7506511            }
 7506512            ResolveActualParameters(e.Bindings, formals, e.tok, fnType, resolutionContext, new Dictionary<TypeParameter,
 7506513            r = new ApplyExpr(e.Lhs.tok, e.Lhs, e.Args, e.CloseParen);
 7506514            r.Type = fnType.Result;
 7506515          }
 81206516        }
 81206517      }
 81206518      if (r == null) {
 6519        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06520        e.Type = new InferredTypeProxy();
 81206521      } else {
 81206522        e.ResolvedExpression = r;
 81206523        e.Type = r.Type;
 81206524      }
 81206525      return null;
 199106526    }
 6527
 6528    /// <summary>
 6529    /// the return value is false iff there is an error in resolving the datatype value;
 6530    /// if there is an error then an error message is emitted iff complain is true
 6531    /// </summary>
 1597406532    private bool ResolveDatatypeValue(ResolutionContext resolutionContext, DatatypeValue dtv, DatatypeDecl dt, Type ty, 
 6533      Contract.Requires(resolutionContext != null);
 6534      Contract.Requires(dtv != null);
 6535      Contract.Requires(dt != null);
 6536      Contract.Requires(ty == null || (ty.AsDatatype == dt && ty.TypeArgs.Count == dt.TypeArgs.Count));
 6537
 1597406538      var ok = true;
 1597406539      var gt = new List<Type>(dt.TypeArgs.Count);
 1597406540      var subst = new Dictionary<TypeParameter, Type>();
 12094606541      for (int i = 0; i < dt.TypeArgs.Count; i++) {
 2966606542        Type t = ty == null ? new InferredTypeProxy() : ty.TypeArgs[i];
 2966606543        gt.Add(t);
 2966606544        dtv.InferredTypeArgs.Add(t);
 2966606545        subst.Add(dt.TypeArgs[i], t);
 2966606546      }
 6547      // Construct a resolved type directly, as we know the declaration is dt.
 1597406548      dtv.Type = new UserDefinedType(dtv.tok, dt.Name, dt, gt);
 6549
 1597406550      if (!dt.ConstructorsByName.TryGetValue(dtv.MemberName, out var ctor)) {
 06551        ok = false;
 06552        if (complain) {
 06553          reporter.Error(MessageSource.Resolver, dtv.tok, "undeclared constructor {0} in datatype {1}", dtv.MemberName, 
 06554        }
 1597406555      } else {
 1597406556        Contract.Assert(ctor != null);  // follows from postcondition of TryGetValue
 1597406557        dtv.Ctor = ctor;
 1597406558      }
 3194806559      if (complain && ctor != null) {
 1597406560        ResolveActualParameters(dtv.Bindings, ctor.Formals, dtv.tok, ctor, resolutionContext, subst, null);
 1597406561      } else {
 6562        // still resolve the expressions
 06563        foreach (var binding in dtv.Bindings.ArgumentBindings) {
 06564          ResolveExpression(binding.Actual, resolutionContext);
 06565        }
 06566        dtv.Bindings.AcceptArgumentExpressionsAsExactParameterList();
 06567      }
 6568
 1597406569      return ok && ctor.Formals.Count == dtv.Arguments.Count;
 1597406570    }
 6571
 06572    public void ResolveFunctionCallExpr(FunctionCallExpr e, ResolutionContext resolutionContext) {
 6573      Contract.Requires(e != null);
 6574      Contract.Requires(e.Type == null);  // should not have been type checked before
 6575
 06576      ResolveReceiver(e.Receiver, resolutionContext);
 06577      Contract.Assert(e.Receiver.Type != null);  // follows from postcondition of ResolveExpression
 6578
 06579      var member = ResolveMember(e.tok, e.Receiver.Type, e.Name, out var tentativeReceiverType);
 6580#if !NO_WORK_TO_BE_DONE
 06581      var ctype = (UserDefinedType)tentativeReceiverType;
 6582#endif
 06583      if (member == null) {
 6584        // error has already been reported by ResolveMember
 06585      } else if (member is Method) {
 06586        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} refers to a method, but only functions can be 
 06587      } else if (!(member is Function)) {
 06588        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} does not refer to a function", e.Name, cce.Non
 06589      } else {
 06590        Function function = (Function)member;
 06591        e.Function = function;
 06592        if (function is TwoStateFunction && !resolutionContext.IsTwoState) {
 06593          reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context");
 06594        }
 06595        if (e.Receiver is StaticReceiverExpr && !function.IsStatic) {
 06596          reporter.Error(MessageSource.Resolver, e, "an instance function must be selected via an object, not just a cla
 06597        }
 06598        Contract.Assert(ctype != null);  // follows from postcondition of ResolveMember
 06599        if (!function.IsStatic) {
 06600          if (!scope.AllowInstance && e.Receiver is ThisExpr) {
 6601            // The call really needs an instance, but that instance is given as 'this', which is not
 6602            // available in this context.  In most cases, occurrences of 'this' inside e.Receiver would
 6603            // have been caught in the recursive call to resolve e.Receiver, but not the specific case
 6604            // of e.Receiver being 'this' (explicitly or implicitly), for that case needs to be allowed
 6605            // in the event that a static function calls another static function (and note that we need the
 6606            // type of the receiver in order to find the method, so we could not have made this check
 6607            // earlier).
 06608            reporter.Error(MessageSource.Resolver, e.Receiver, "'this' is not allowed in a 'static' context");
 06609          } else if (e.Receiver is StaticReceiverExpr) {
 06610            reporter.Error(MessageSource.Resolver, e.Receiver, "call to instance function requires an instance");
 06611          }
 06612        }
 6613        // build the type substitution map
 06614        var typeMap = new Dictionary<TypeParameter, Type>();
 06615        for (int i = 0; i < ctype.TypeArgs.Count; i++) {
 06616          typeMap.Add(ctype.ResolvedClass.TypeArgs[i], ctype.TypeArgs[i]);
 06617        }
 06618        var typeThatEnclosesMember = ctype.AsParentType(member.EnclosingClass);
 06619        e.TypeApplication_AtEnclosingClass = new List<Type>();
 06620        for (int i = 0; i < typeThatEnclosesMember.TypeArgs.Count; i++) {
 06621          e.TypeApplication_AtEnclosingClass.Add(typeThatEnclosesMember.TypeArgs[i]);
 06622        }
 06623        e.TypeApplication_JustFunction = new List<Type>();
 06624        foreach (TypeParameter p in function.TypeArgs) {
 06625          var ty = new ParamTypeProxy(p);
 06626          typeMap.Add(p, ty);
 06627          e.TypeApplication_JustFunction.Add(ty);
 06628        }
 06629        Dictionary<TypeParameter, Type> subst = BuildTypeArgumentSubstitute(typeMap);
 6630
 6631        // type check the arguments
 06632        ResolveActualParameters(e.Bindings, function.Formals, e.tok, function, resolutionContext, subst, function.IsStat
 6633
 06634        e.Type = function.ResultType.Subst(subst).NormalizeExpand();
 06635      }
 06636    }
 6637
 06638    void ResolveReceiver(Expression expr, ResolutionContext resolutionContext) {
 6639      Contract.Requires(expr != null);
 6640      Contract.Ensures(expr.Type != null);
 6641
 06642      if (expr is ThisExpr && !expr.WasResolved()) {
 6643        // Allow 'this' here, regardless of scope.AllowInstance.  The caller is responsible for
 6644        // making sure 'this' does not really get used when it's not available.
 06645        Contract.Assume(currentClass != null);  // this is really a precondition, in this case
 06646        expr.Type = GetThisType(expr.tok, currentClass);
 06647      } else {
 06648        ResolveExpression(expr, resolutionContext);
 06649      }
 06650    }
 6651
 129106652    void ResolveSeqSelectExpr(SeqSelectExpr e, ResolutionContext resolutionContext) {
 6653      Contract.Requires(e != null);
 129106654      if (e.Type != null) {
 6655        // already resolved
 06656        return;
 6657      }
 6658
 129106659      ResolveExpression(e.Seq, resolutionContext);
 129106660      Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 6661
 142006662      if (e.SelectOne) {
 12906663        AddXConstraint(e.tok, "Indexable", e.Seq.Type, "element selection requires a sequence, array, multiset, or map (
 12906664        ResolveExpression(e.E0, resolutionContext);
 12906665        AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got {1
 12906666        Contract.Assert(e.E1 == null);
 12906667        e.Type = new InferredTypeProxy() { KeepConstraints = true };
 12906668        AddXConstraint(e.tok, "ContainerResult",
 12906669          e.Seq.Type, e.Type,
 12906670          new SeqSelectOneErrorMsg(e.tok, e.Seq.Type, e.Type));
 129106671      } else {
 116206672        AddXConstraint(e.tok, "MultiIndexable", e.Seq.Type, "multi-selection of elements requires a sequence or array (g
 190906673        if (e.E0 != null) {
 74706674          ResolveExpression(e.E0, resolutionContext);
 74706675          AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got 
 74706676          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E0.Type, e.E0, "wrong number of indices for multi-sele
 74706677        }
 207506678        if (e.E1 != null) {
 91306679          ResolveExpression(e.E1, resolutionContext);
 91306680          AddXConstraint(e.E1.tok, "ContainerIndex", e.Seq.Type, e.E1.Type, "incorrect type for selection into {0} (got 
 91306681          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E1.Type, e.E1, "wrong number of indices for multi-sele
 91306682        }
 116206683        var resultType = new InferredTypeProxy() { KeepConstraints = true };
 116206684        e.Type = new SeqType(resultType);
 116206685        AddXConstraint(e.tok, "ContainerResult", e.Seq.Type, resultType, "multi-selection has type {0} which is incompat
 116206686      }
 129106687    }
 6688
 6689  }
 6690
 6691  public class MethodCallInformation {
 6692    public readonly IToken Tok;
 6693    public readonly MemberSelectExpr Callee;
 6694    public readonly List<ActualBinding> ActualParameters;
 6695
 6696    [ContractInvariantMethod]
 6697    void ObjectInvariant() {
 6698      Contract.Invariant(Tok != null);
 6699      Contract.Invariant(Callee != null);
 6700      Contract.Invariant(Callee.Member is Method);
 6701      Contract.Invariant(ActualParameters != null);
 6702    }
 6703
 6704    public MethodCallInformation(IToken tok, MemberSelectExpr callee, List<ActualBinding> actualParameters) {
 6705      Contract.Requires(tok != null);
 6706      Contract.Requires(callee != null);
 6707      Contract.Requires(callee.Member is Method);
 6708      Contract.Requires(actualParameters != null);
 6709      this.Tok = tok;
 6710      this.Callee = callee;
 6711      this.ActualParameters = actualParameters;
 6712    }
 6713  }
 6714}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/Resolver.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 4// Copyright by the contributors to the Dafny Project
 5// SPDX-License-Identifier: MIT
 6//
 7//-----------------------------------------------------------------------------
 8using System;
 9using System.Collections.Generic;
 10using System.Linq;
 11using System.Numerics;
 12using System.Diagnostics.Contracts;
 13using System.IO;
 14using System.Reflection;
 15using JetBrains.Annotations;
 16using Microsoft.BaseTypes;
 17using Microsoft.Boogie;
 18using Microsoft.CodeAnalysis.CSharp.Syntax;
 19using Microsoft.Dafny.Plugins;
 20using static Microsoft.Dafny.ErrorRegistry;
 21
 22namespace Microsoft.Dafny {
 23  interface ICanResolve {
 24    void Resolve(Resolver resolver, ResolutionContext context);
 25  }
 26
 27  public enum FrameExpressionUse { Reads, Modifies, Unchanged }
 28
 29  public partial class Resolver {
 14925535530    public DafnyOptions Options { get; }
 31    public readonly BuiltIns builtIns;
 32
 33    public ErrorReporter reporter;
 41534    ModuleSignature moduleInfo = null;
 35
 118661536    public ErrorReporter Reporter => reporter;
 15496537    public List<TypeConstraint.ErrorMsg> TypeConstraintErrorsToBeReported { get; } = new();
 38
 039    private bool RevealedInScope(Declaration d) {
 40      Contract.Requires(d != null);
 41      Contract.Requires(moduleInfo != null);
 42      Contract.Requires(moduleInfo.VisibilityScope != null);
 43
 044      return useCompileSignatures || d.IsRevealedInScope(moduleInfo.VisibilityScope);
 045    }
 46
 5021047    private bool VisibleInScope(Declaration d) {
 48      Contract.Requires(d != null);
 49      Contract.Requires(moduleInfo != null);
 50      Contract.Requires(moduleInfo.VisibilityScope != null);
 51
 5021052      return useCompileSignatures || d.IsVisibleInScope(moduleInfo.VisibilityScope);
 5021053    }
 54
 41555    public FreshIdGenerator defaultTempVarIdGenerator = new FreshIdGenerator();
 56
 057    public string FreshTempVarName(string prefix, ICodeContext context) {
 058      var gen = context is Declaration decl ? decl.IdGenerator : defaultTempVarIdGenerator;
 059      var freshTempVarName = gen.FreshId(prefix);
 060      return freshTempVarName;
 061    }
 62
 63    interface IAmbiguousThing<Thing> {
 64      /// <summary>
 65      /// Returns a plural number of non-null Thing's
 66      /// </summary>
 67      ISet<Thing> Pool { get; }
 68    }
 69
 70    class AmbiguousThingHelper<Thing> where Thing : class {
 071      public static Thing Create(ModuleDefinition m, Thing a, Thing b, IEqualityComparer<Thing> eq, out ISet<Thing> s) {
 72        Contract.Requires(a != null);
 73        Contract.Requires(b != null);
 74        Contract.Requires(eq != null);
 75        Contract.Ensures(Contract.Result<Thing>() != null ||
 76                         Contract.ValueAtReturn(out s) != null || 2 <= Contract.ValueAtReturn(out s).Count);
 077        s = null;
 078        if (eq.Equals(a, b)) {
 079          return a;
 80        }
 81
 082        ISet<Thing> sa = a is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)a).Pool : new HashSet<Thing>() { a };
 083        ISet<Thing> sb = b is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)b).Pool : new HashSet<Thing>() { b };
 084        var union = new HashSet<Thing>(sa.Union(sb, eq));
 085        if (sa.Count == union.Count) {
 86          // sb is a subset of sa
 087          return a;
 088        } else if (sb.Count == union.Count) {
 89          // sa is a subset of sb
 090          return b;
 091        } else {
 092          s = union;
 093          Contract.Assert(2 <= s.Count);
 094          return null;
 95        }
 096      }
 97
 098      public static string Name(ISet<Thing> s, Func<Thing, string> name) {
 99        Contract.Requires(s != null);
 100        Contract.Requires(s.Count != 0);
 0101        string nm = null;
 0102        foreach (var thing in s) {
 0103          string n = name(thing);
 0104          if (nm == null) {
 0105            nm = n;
 0106          } else {
 0107            nm += "/" + n;
 0108          }
 0109        }
 110
 0111        return nm;
 0112      }
 113
 0114      public static string ModuleNames(IAmbiguousThing<Thing> amb, Func<Thing, string> moduleName) {
 115        Contract.Requires(amb != null);
 116        Contract.Ensures(Contract.Result<string>() != null);
 0117        string nm = null;
 0118        foreach (var d in amb.Pool) {
 0119          if (nm == null) {
 0120            nm = moduleName(d);
 0121          } else {
 0122            nm += ", " + moduleName(d);
 0123          }
 0124        }
 125
 0126        return nm;
 0127      }
 128    }
 129
 130    public class AmbiguousTopLevelDecl : TopLevelDecl, IAmbiguousThing<TopLevelDecl> // only used with "classes"
 131    {
 0132      public static TopLevelDecl Create(ModuleDefinition m, TopLevelDecl a, TopLevelDecl b) {
 0133        var t = AmbiguousThingHelper<TopLevelDecl>.Create(m, a, b, new Eq(), out var s);
 0134        return t ?? new AmbiguousTopLevelDecl(m, AmbiguousThingHelper<TopLevelDecl>.Name(s, tld => tld.Name), s);
 0135      }
 136
 137      class Eq : IEqualityComparer<TopLevelDecl> {
 0138        public bool Equals(TopLevelDecl d0, TopLevelDecl d1) {
 139          // We'd like to resolve any AliasModuleDecl to whatever module they refer to.
 140          // It seems that the only way to do that is to look at alias.Signature.ModuleDef,
 141          // but that is a ModuleDefinition, which is not a TopLevelDecl.  Therefore, we
 142          // convert to a ModuleDefinition anything that might refer to something that an
 143          // AliasModuleDecl can refer to; this is AliasModuleDecl and LiteralModuleDecl.
 0144          object a = d0 is ModuleDecl ? ((ModuleDecl)d0).Dereference() : d0;
 0145          object b = d1 is ModuleDecl ? ((ModuleDecl)d1).Dereference() : d1;
 0146          return a == b;
 0147        }
 148
 0149        public int GetHashCode(TopLevelDecl d) {
 0150          object a = d is ModuleDecl ? ((ModuleDecl)d).Dereference() : d;
 0151          return a.GetHashCode();
 0152        }
 153      }
 154
 155      public override string WhatKind {
 0156        get { return Pool.First().WhatKind; }
 157      }
 158
 0159      readonly ISet<TopLevelDecl> Pool = new HashSet<TopLevelDecl>();
 160
 161      ISet<TopLevelDecl> IAmbiguousThing<TopLevelDecl>.Pool {
 0162        get { return Pool; }
 163      }
 164
 165      private AmbiguousTopLevelDecl(ModuleDefinition m, string name, ISet<TopLevelDecl> pool)
 0166        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), m, new List<TypeParameter>(), null, fal
 167        Contract.Requires(name != null);
 168        Contract.Requires(pool != null && 2 <= pool.Count);
 0169        Pool = pool;
 0170      }
 171
 0172      public string ModuleNames() {
 0173        return AmbiguousThingHelper<TopLevelDecl>.ModuleNames(this, d => d.EnclosingModuleDefinition.Name);
 0174      }
 175    }
 176
 177    class AmbiguousMemberDecl : MemberDecl, IAmbiguousThing<MemberDecl> // only used with "classes"
 178    {
 0179      public static MemberDecl Create(ModuleDefinition m, MemberDecl a, MemberDecl b) {
 180        ISet<MemberDecl> s;
 0181        var t = AmbiguousThingHelper<MemberDecl>.Create(m, a, b, new Eq(), out s);
 0182        return t ?? new AmbiguousMemberDecl(m, AmbiguousThingHelper<MemberDecl>.Name(s, member => member.Name), s);
 0183      }
 184
 185      class Eq : IEqualityComparer<MemberDecl> {
 0186        public bool Equals(MemberDecl d0, MemberDecl d1) {
 0187          return d0 == d1;
 0188        }
 189
 0190        public int GetHashCode(MemberDecl d) {
 0191          return d.GetHashCode();
 0192        }
 193      }
 194
 195      public override string WhatKind {
 0196        get { return Pool.First().WhatKind; }
 197      }
 198
 0199      readonly ISet<MemberDecl> Pool = new HashSet<MemberDecl>();
 200
 201      ISet<MemberDecl> IAmbiguousThing<MemberDecl>.Pool {
 0202        get { return Pool; }
 203      }
 204
 205      private AmbiguousMemberDecl(ModuleDefinition m, string name, ISet<MemberDecl> pool)
 0206        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), true, pool.First().IsGhost, null, false
 207        Contract.Requires(name != null);
 208        Contract.Requires(pool != null && 2 <= pool.Count);
 0209        Pool = pool;
 0210      }
 211
 0212      public string ModuleNames() {
 0213        return AmbiguousThingHelper<MemberDecl>.ModuleNames(this, d => d.EnclosingClass.EnclosingModuleDefinition.Name);
 0214      }
 215    }
 216
 415217    readonly HashSet<RevealableTypeDecl> revealableTypes = new HashSet<RevealableTypeDecl>();
 218    //types that have been seen by the resolver - used for constraining type inference during exports
 219
 415220    public readonly Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>> classMembers =
 415221      new Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>>();
 222
 223    enum ValuetypeVariety {
 224      Bool = 0,
 225      Int,
 226      Real,
 227      BigOrdinal,
 228      Bitvector,
 229      Map,
 230      IMap,
 231      None
 232    } // note, these are ordered, so they can be used as indices into valuetypeDecls
 233
 234    internal readonly ValuetypeDecl[] valuetypeDecls;
 235    private Dictionary<TypeParameter, Type> SelfTypeSubstitution;
 415236    readonly Graph<ModuleDecl> dependencies = new Graph<ModuleDecl>();
 415237    private ModuleSignature systemNameInfo = null;
 415238    private bool useCompileSignatures = false;
 239
 240    private List<IRewriter> rewriters;
 241    private RefinementTransformer refinementTransformer;
 242
 0243    public Resolver(DafnyOptions options) {
 0244      Options = options;
 0245    }
 246
 830247    public Resolver(Program prog) {
 415248      Options = prog.Options;
 249
 415250      allTypeParameters = new Scope<TypeParameter>(Options);
 415251      scope = new Scope<IVariable>(Options);
 415252      enclosingStatementLabels = new Scope<Statement>(Options);
 415253      DominatingStatementLabels = new Scope<Label>(Options);
 254
 255      Contract.Requires(prog != null);
 256
 415257      builtIns = prog.BuiltIns;
 415258      reporter = prog.Reporter;
 259
 260      // Map#Items relies on the two destructors for 2-tuples
 415261      builtIns.TupleType(Token.NoToken, 2, true);
 262      // Several methods and fields rely on 1-argument arrow types
 415263      builtIns.CreateArrowTypeDecl(1);
 264
 415265      valuetypeDecls = new ValuetypeDecl[] {
 8460266        new ValuetypeDecl("bool", builtIns.SystemModule, t => t.IsBoolType, typeArgs => Type.Bool),
 8460267        new ValuetypeDecl("int", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Int), typeArgs => T
 8460268        new ValuetypeDecl("real", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Real), typeArgs =>
 8460269        new ValuetypeDecl("ORDINAL", builtIns.SystemModule, t => t.IsBigOrdinalType, typeArgs => Type.BigOrdinal),
 8460270        new ValuetypeDecl("_bv", builtIns.SystemModule, t => t.IsBitVectorType, null), // "_bv" represents a family of c
 415271        new ValuetypeDecl("map", builtIns.SystemModule,
 415272          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Strict , TypeParameter.T
 8460273          t => t.IsMapType, typeArgs => new MapType(true, typeArgs[0], typeArgs[1])),
 415274        new ValuetypeDecl("imap", builtIns.SystemModule,
 415275          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Permissive , TypeParamet
 8460276          t => t.IsIMapType, typeArgs => new MapType(false, typeArgs[0], typeArgs[1]))
 415277      };
 415278      builtIns.SystemModule.TopLevelDecls.AddRange(valuetypeDecls);
 279      // Resolution error handling relies on being able to get to the 0-tuple declaration
 415280      builtIns.TupleType(Token.NoToken, 0, true);
 281
 282      // Populate the members of the basic types
 283
 4565284      void AddMember(MemberDecl member, ValuetypeVariety valuetypeVariety) {
 4565285        var enclosingType = valuetypeDecls[(int)valuetypeVariety];
 4565286        member.EnclosingClass = enclosingType;
 4565287        member.AddVisibilityScope(prog.BuiltIns.SystemModule.VisibilityScope, false);
 4565288        enclosingType.Members.Add(member.Name, member);
 4565289      }
 290
 415291      var floor = new SpecialField(RangeToken.NoToken, "Floor", SpecialField.ID.Floor, null, false, false, false, Type.I
 415292      AddMember(floor, ValuetypeVariety.Real);
 293
 415294      var isLimit = new SpecialField(RangeToken.NoToken, "IsLimit", SpecialField.ID.IsLimit, null, false, false, false, 
 415295      AddMember(isLimit, ValuetypeVariety.BigOrdinal);
 296
 415297      var isSucc = new SpecialField(RangeToken.NoToken, "IsSucc", SpecialField.ID.IsSucc, null, false, false, false, Typ
 415298      AddMember(isSucc, ValuetypeVariety.BigOrdinal);
 299
 415300      var limitOffset = new SpecialField(RangeToken.NoToken, "Offset", SpecialField.ID.Offset, null, false, false, false
 415301      AddMember(limitOffset, ValuetypeVariety.BigOrdinal);
 415302      builtIns.ORDINAL_Offset = limitOffset;
 303
 415304      var isNat = new SpecialField(RangeToken.NoToken, "IsNat", SpecialField.ID.IsNat, null, false, false, false, Type.B
 415305      AddMember(isNat, ValuetypeVariety.BigOrdinal);
 306
 307      // Add "Keys", "Values", and "Items" to map, imap
 3735308      foreach (var typeVariety in new[] { ValuetypeVariety.Map, ValuetypeVariety.IMap }) {
 830309        var vtd = valuetypeDecls[(int)typeVariety];
 830310        var isFinite = typeVariety == ValuetypeVariety.Map;
 311
 830312        var r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[0]));
 830313        var keys = new SpecialField(RangeToken.NoToken, "Keys", SpecialField.ID.Keys, null, false, false, false, r, null
 314
 830315        r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[1]));
 830316        var values = new SpecialField(RangeToken.NoToken, "Values", SpecialField.ID.Values, null, false, false, false, r
 317
 2490318        var gt = vtd.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 830319        var dt = builtIns.TupleType(Token.NoToken, 2, true);
 830320        var tupleType = new UserDefinedType(Token.NoToken, dt.Name, dt, gt);
 830321        r = new SetType(isFinite, tupleType);
 830322        var items = new SpecialField(RangeToken.NoToken, "Items", SpecialField.ID.Items, null, false, false, false, r, n
 323
 9960324        foreach (var memb in new[] { keys, values, items }) {
 2490325          AddMember(memb, typeVariety);
 2490326        }
 830327      }
 328
 329      // The result type of the following bitvector methods is the type of the bitvector itself. However, we're represen
 330      // a family of types rolled up in one ValuetypeDecl. Therefore, we use the special SelfType as the result type.
 415331      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateLeft", new SelfType());
 415332      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateRight", new SelfType());
 415333    }
 334
 830335    public void AddRotateMember(ValuetypeDecl enclosingType, string name, Type resultType) {
 830336      var formals = new List<Formal> { new Formal(Token.NoToken, "w", Type.Nat(), true, false, null, false) };
 830337      var rotateMember = new SpecialFunction(RangeToken.NoToken, name, builtIns.SystemModule, false, false,
 830338        new List<TypeParameter>(), formals, resultType,
 830339        new List<AttributedExpression>(), new List<FrameExpression>(), new List<AttributedExpression>(),
 830340        new Specification<Expression>(new List<Expression>(), null), null, null, null);
 830341      rotateMember.EnclosingClass = enclosingType;
 830342      rotateMember.AddVisibilityScope(builtIns.SystemModule.VisibilityScope, false);
 830343      enclosingType.Members.Add(name, rotateMember);
 830344    }
 345
 346    [ContractInvariantMethod]
 0347    void ObjectInvariant() {
 348      Contract.Invariant(builtIns != null);
 349      Contract.Invariant(cce.NonNullElements(dependencies.GetVertices()));
 350      Contract.Invariant(cce.NonNullDictionaryAndValues(classMembers) && Contract.ForAll(classMembers.Values, v => cce.N
 0351    }
 352
 0353    public ValuetypeDecl AsValuetypeDecl(Type t) {
 354      Contract.Requires(t != null);
 0355      foreach (var vtd in valuetypeDecls) {
 0356        if (vtd.IsThisType(t)) {
 0357          return vtd;
 358        }
 0359      }
 0360      return null;
 0361    }
 362
 363    /// <summary>
 364    /// Check that now two modules that are being compiled have the same CompileName.
 365    ///
 366    /// This could happen if they are given the same name using the 'extern' declaration modifier.
 367    /// </summary>
 368    /// <param name="prog">The Dafny program being compiled.</param>
 415369    void CheckDupModuleNames(Program prog) {
 370      // Check that none of the modules have the same CompileName.
 415371      Dictionary<string, ModuleDefinition> compileNameMap = new Dictionary<string, ModuleDefinition>();
 3735372      foreach (ModuleDefinition m in prog.CompileModules) {
 830373        var compileIt = true;
 830374        Attributes.ContainsBool(m.Attributes, "compile", ref compileIt);
 830375        if (m.IsAbstract || !compileIt) {
 376          // the purpose of an abstract module is to skip compilation
 0377          continue;
 378        }
 830379        string compileName = m.GetCompileName(Options);
 380        ModuleDefinition priorModDef;
 830381        if (compileNameMap.TryGetValue(compileName, out priorModDef)) {
 0382          reporter.Error(MessageSource.Resolver, m.tok,
 0383            "modules '{0}' and '{1}' both have CompileName '{2}'",
 0384            priorModDef.tok.val, m.tok.val, compileName);
 830385        } else {
 830386          compileNameMap.Add(compileName, m);
 830387        }
 830388      }
 415389    }
 390
 415391    public void ResolveProgram(Program prog) {
 392      Contract.Requires(prog != null);
 415393      Type.ResetScopes();
 394
 415395      Type.EnableScopes();
 396      // For the formatter, we ensure we take snapshots of the PrefixNamedModules
 397      // and topleveldecls
 415398      prog.DefaultModuleDef.PreResolveSnapshotForFormatter();
 415399      var origErrorCount = reporter.ErrorCount; //TODO: This is used further below, but not in the >0 comparisons in the
 415400      var bindings = new ModuleBindings(null);
 415401      var b = BindModuleNames(prog.DefaultModuleDef, bindings);
 415402      bindings.BindName(prog.DefaultModule.Name, prog.DefaultModule, b);
 415403      if (reporter.ErrorCount > 0) {
 0404        return;
 405      } // if there were errors, then the implict ModuleBindings data structure invariant
 406
 407      // is violated, so Processing dependencies will not succeed.
 415408      ProcessDependencies(prog.DefaultModule, b, dependencies);
 409      // check for cycles in the import graph
 1245410      foreach (var cycle in dependencies.AllCycles()) {
 0411        ReportCycleError(cycle, m => m.tok,
 0412          m => (m is AliasModuleDecl ? "import " : "module ") + m.Name,
 0413          "module definition contains a cycle (note: parent modules implicitly depend on submodules)");
 0414      }
 415
 415416      if (reporter.ErrorCount > 0) {
 0417        return;
 418      } // give up on trying to resolve anything else
 419
 420      // fill in module heights
 415421      List<ModuleDecl> sortedDecls = dependencies.TopologicallySortedComponents();
 415422      int h = 0;
 2490423      foreach (ModuleDecl md in sortedDecls) {
 415424        md.Height = h;
 830425        if (md is LiteralModuleDecl) {
 415426          var mdef = ((LiteralModuleDecl)md).ModuleDef;
 415427          mdef.Height = h;
 415428          prog.ModuleSigs.Add(mdef, null);
 415429        }
 415430        h++;
 415431      }
 432
 415433      rewriters = new List<IRewriter>();
 434
 415435      if (Options.AuditProgram) {
 0436        rewriters.Add(new Auditor.Auditor(reporter));
 0437      }
 438
 415439      refinementTransformer = new RefinementTransformer(prog);
 415440      rewriters.Add(refinementTransformer);
 830441      if (!Options.VerifyAllModules) {
 415442        rewriters.Add(new IncludedLemmaBodyRemover(prog, reporter));
 415443      }
 415444      rewriters.Add(new AutoContractsRewriter(reporter, builtIns));
 415445      rewriters.Add(new OpaqueMemberRewriter(this.reporter));
 415446      rewriters.Add(new AutoReqFunctionRewriter(this.reporter, this.builtIns));
 415447      rewriters.Add(new TimeLimitRewriter(reporter));
 415448      rewriters.Add(new ForallStmtRewriter(reporter));
 415449      rewriters.Add(new ProvideRevealAllRewriter(this.reporter));
 415450      rewriters.Add(new MatchFlattener(this.reporter, defaultTempVarIdGenerator));
 451
 830452      if (Options.AutoTriggers) {
 415453        rewriters.Add(new QuantifierSplittingRewriter(reporter));
 415454        rewriters.Add(new TriggerGeneratingRewriter(reporter));
 415455      }
 456
 415457      if (Options.TestContracts != DafnyOptions.ContractTestingMode.None) {
 0458        rewriters.Add(new ExpectContracts(reporter));
 0459      }
 460
 415461      if (Options.RunAllTests) {
 0462        rewriters.Add(new RunAllTestsMainMethod(reporter));
 0463      }
 464
 415465      rewriters.Add(new InductionRewriter(reporter));
 415466      rewriters.Add(new PrintEffectEnforcement(reporter));
 415467      rewriters.Add(new BitvectorOptimization(reporter));
 468
 415469      if (Options.DisallowConstructorCaseWithoutParentheses) {
 0470        rewriters.Add(new ConstructorWarning(reporter));
 0471      }
 415472      rewriters.Add(new LocalLinter(reporter));
 415473      rewriters.Add(new PrecedenceLinter(reporter));
 474
 3735475      foreach (var plugin in Options.Plugins) {
 830476        rewriters.AddRange(plugin.GetRewriters(reporter));
 830477      }
 478
 415479      systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule, false);
 415480      prog.CompileModules.Add(prog.BuiltIns.SystemModule);
 415481      RevealAllInScope(prog.BuiltIns.SystemModule.TopLevelDecls, systemNameInfo.VisibilityScope);
 415482      ResolveValuetypeDecls();
 483      // The SystemModule is constructed with all its members already being resolved. Except for
 484      // the non-null type corresponding to class types.  They are resolved here:
 415485      var systemModuleClassesWithNonNullTypes =
 13380486        prog.BuiltIns.SystemModule.TopLevelDecls.Where(d => (d as ClassDecl)?.NonNullTypeDecl != null).ToList();
 3735487      foreach (var cl in systemModuleClassesWithNonNullTypes) {
 830488        var d = ((ClassDecl)cl).NonNullTypeDecl;
 830489        allTypeParameters.PushMarker();
 830490        ResolveTypeParameters(d.TypeArgs, true, d);
 830491        ResolveType(d.tok, d.Rhs, d, ResolveTypeOptionEnum.AllowPrefix, d.TypeArgs);
 830492        allTypeParameters.PopMarker();
 830493      }
 415494      ResolveTopLevelDecls_Core(ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(systemModuleClassesWithNonNullTypes)
 415495        new Graph<IndDatatypeDecl>(), new Graph<CoDatatypeDecl>(), prog.BuiltIns.SystemModule.Name);
 496
 21165497      foreach (var rewriter in rewriters) {
 6640498        rewriter.PreResolve(prog);
 6640499      }
 500
 415501      var compilationModuleClones = new Dictionary<ModuleDefinition, ModuleDefinition>();
 2490502      foreach (var decl in sortedDecls) {
 830503        if (decl is LiteralModuleDecl) {
 504          // The declaration is a literal module, so it has members and such that we need
 505          // to resolve. First we do refinement transformation. Then we construct the signature
 506          // of the module. This is the public, externally visible signature. Then we add in
 507          // everything that the system defines, as well as any "import" (i.e. "opened" modules)
 508          // directives (currently not supported, but this is where we would do it.) This signature,
 509          // which is only used while resolving the members of the module is stored in the (basically)
 510          // global variable moduleInfo. Then the signatures of the module members are resolved, followed
 511          // by the bodies.
 415512          var literalDecl = (LiteralModuleDecl)decl;
 415513          var m = literalDecl.ModuleDef;
 514
 415515          var errorCount = reporter.ErrorCount;
 415516          if (m.RefinementQId != null) {
 0517            ModuleDecl md = ResolveModuleQualifiedId(m.RefinementQId.Root, m.RefinementQId, reporter);
 0518            m.RefinementQId.Set(md); // If module is not found, md is null and an error message has been emitted
 0519          }
 520
 21165521          foreach (var rewriter in rewriters) {
 6640522            rewriter.PreResolve(m);
 6640523          }
 524
 415525          literalDecl.Signature = RegisterTopLevelDecls(m, true);
 415526          literalDecl.Signature.Refines = refinementTransformer.RefinedSig;
 527
 415528          var sig = literalDecl.Signature;
 529          // set up environment
 415530          var preResolveErrorCount = reporter.ErrorCount;
 531
 415532          ResolveModuleExport(literalDecl, sig);
 415533          var good = ResolveModuleDefinition(m, sig);
 534
 830535          if (good && reporter.ErrorCount == preResolveErrorCount) {
 536            // Check that the module export gives a self-contained view of the module.
 415537            CheckModuleExportConsistency(m);
 415538          }
 539
 415540          var tempVis = new VisibilityScope();
 415541          tempVis.Augment(sig.VisibilityScope);
 415542          tempVis.Augment(systemNameInfo.VisibilityScope);
 415543          Type.PushScope(tempVis);
 544
 415545          prog.ModuleSigs[m] = sig;
 546
 21165547          foreach (var rewriter in rewriters) {
 6640548            if (!good || reporter.ErrorCount != preResolveErrorCount) {
 0549              break;
 550            }
 6640551            rewriter.PostResolveIntermediate(m);
 6640552          }
 830553          if (good && reporter.ErrorCount == errorCount) {
 415554            m.SuccessfullyResolved = true;
 415555          }
 415556          Type.PopScope(tempVis);
 557
 830558          if (reporter.ErrorCount == errorCount && !m.IsAbstract) {
 559            // compilation should only proceed if everything is good, including the signature (which preResolveErrorCoun
 415560            CompilationCloner cloner = new CompilationCloner(compilationModuleClones);
 415561            var nw = cloner.CloneModuleDefinition(m, new Name(m.NameNode.RangeToken, m.GetCompileName(Options) + "_Compi
 415562            compilationModuleClones.Add(m, nw);
 415563            var oldErrorsOnly = reporter.ErrorsOnly;
 415564            reporter.ErrorsOnly = true; // turn off warning reporting for the clone
 565            // Next, compute the compile signature
 415566            Contract.Assert(!useCompileSignatures);
 415567            useCompileSignatures = true; // set Resolver-global flag to indicate that Signatures should be followed to t
 415568            Type.DisableScopes();
 415569            var compileSig = RegisterTopLevelDecls(nw, true);
 415570            compileSig.Refines = refinementTransformer.RefinedSig;
 415571            sig.CompileSignature = compileSig;
 1245572            foreach (var exportDecl in sig.ExportSets.Values) {
 0573              exportDecl.Signature.CompileSignature = cloner.CloneModuleSignature(exportDecl.Signature, compileSig);
 0574            }
 575            // Now we're ready to resolve the cloned module definition, using the compile signature
 576
 415577            ResolveModuleDefinition(nw, compileSig);
 578
 21165579            foreach (var rewriter in rewriters) {
 6640580              rewriter.PostCompileCloneAndResolve(nw);
 6640581            }
 582
 415583            prog.CompileModules.Add(nw);
 415584            useCompileSignatures = false; // reset the flag
 415585            Type.EnableScopes();
 415586            reporter.ErrorsOnly = oldErrorsOnly;
 415587          }
 415588        } else if (decl is AliasModuleDecl alias) {
 589          // resolve the path
 590          ModuleSignature p;
 0591          if (ResolveExport(alias, alias.EnclosingModuleDefinition, alias.TargetQId, alias.Exports, out p, reporter)) {
 0592            if (alias.Signature == null) {
 0593              alias.Signature = p;
 0594            }
 0595          } else {
 0596            alias.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0597          }
 0598        } else if (decl is AbstractModuleDecl abs) {
 599          ModuleSignature p;
 0600          if (ResolveExport(abs, abs.EnclosingModuleDefinition, abs.QId, abs.Exports, out p, reporter)) {
 0601            abs.OriginalSignature = p;
 0602            abs.Signature = MakeAbstractSignature(p, abs.FullSanitizedName, abs.Height, prog.ModuleSigs, compilationModu
 0603          } else {
 0604            abs.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0605          }
 0606        } else if (decl is ModuleExportDecl) {
 0607          ((ModuleExportDecl)decl).SetupDefaultSignature();
 608
 0609          Contract.Assert(decl.Signature != null);
 0610          Contract.Assert(decl.Signature.VisibilityScope != null);
 611
 0612        } else {
 0613          Contract.Assert(false); // Unknown kind of ModuleDecl
 0614        }
 615
 415616        Contract.Assert(decl.Signature != null);
 415617      }
 618
 415619      if (reporter.ErrorCount != origErrorCount) {
 620        // do nothing else
 0621        return;
 622      }
 623
 624      // compute IsRecursive bit for mutually recursive functions and methods
 2490625      foreach (var module in prog.Modules()) {
 28200626        foreach (var clbl in ModuleDefinition.AllCallables(module.TopLevelDecls)) {
 15445627          if (clbl is Function) {
 6460628            var fn = (Function)clbl;
 12920629            if (!fn.IsRecursive) { // note, self-recursion has already been determined
 6460630              int n = module.CallGraph.GetSCCSize(fn);
 6460631              if (2 <= n) {
 632                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0633                fn.IsRecursive = true;
 0634              }
 6460635            }
 6460636            if (fn.IsRecursive && fn is ExtremePredicate) {
 637              // this means the corresponding prefix predicate is also recursive
 0638              var prefixPred = ((ExtremePredicate)fn).PrefixPredicate;
 0639              if (prefixPred != null) {
 0640                prefixPred.IsRecursive = true;
 0641              }
 0642            }
 8985643          } else {
 2525644            var m = (Method)clbl;
 5050645            if (!m.IsRecursive) {
 646              // note, self-recursion has already been determined
 2525647              int n = module.CallGraph.GetSCCSize(m);
 2525648              if (2 <= n) {
 649                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0650              }
 2525651            }
 2525652          }
 8985653        }
 654
 21165655        foreach (var rewriter in rewriters) {
 6640656          rewriter.PostCyclicityResolve(module);
 6640657        }
 415658      }
 659
 660      // fill in default decreases clauses:  for functions and methods, and for loops
 415661      new InferDecreasesClause(this).FillInDefaultDecreasesClauses(prog);
 2490662      foreach (var module in prog.Modules()) {
 28200663        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 8985664          Statement body = null;
 11510665          if (clbl is Method) {
 2525666            body = ((Method)clbl).Body;
 8985667          } else if (clbl is IteratorDecl) {
 0668            body = ((IteratorDecl)clbl).Body;
 0669          }
 670
 11510671          if (body != null) {
 2525672            var c = new FillInDefaultLoopDecreases_Visitor(this, clbl);
 2525673            c.Visit(body);
 2525674          }
 8985675        }
 415676      }
 677
 2490678      foreach (var module in prog.Modules()) {
 1245679        foreach (var iter in ModuleDefinition.AllIteratorDecls(module.TopLevelDecls)) {
 0680          reporter.Info(MessageSource.Resolver, iter.tok, Printer.IteratorClassToString(Reporter.Options, iter));
 0681        }
 415682      }
 683
 2490684      foreach (var module in prog.Modules()) {
 21165685        foreach (var rewriter in rewriters) {
 6640686          rewriter.PostDecreasesResolve(module);
 6640687        }
 415688      }
 689
 690      // fill in other additional information
 2490691      foreach (var module in prog.Modules()) {
 28200692        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 8985693          Statement body = null;
 8985694          if (clbl is ExtremeLemma) {
 0695            body = ((ExtremeLemma)clbl).PrefixLemma.Body;
 11510696          } else if (clbl is Method) {
 2525697            body = ((Method)clbl).Body;
 8985698          } else if (clbl is IteratorDecl) {
 0699            body = ((IteratorDecl)clbl).Body;
 0700          }
 701
 11510702          if (body != null) {
 2525703            var c = new ReportOtherAdditionalInformation_Visitor(this);
 2525704            c.Visit(body);
 2525705          }
 8985706        }
 415707      }
 708
 709      // Determine, for each function, whether someone tries to adjust its fuel parameter
 2490710      foreach (var module in prog.Modules()) {
 415711        CheckForFuelAdjustments(module.tok, module.Attributes, module);
 28200712        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 8985713          Statement body = null;
 11510714          if (clbl is Method) {
 2525715            body = ((Method)clbl).Body;
 2525716            CheckForFuelAdjustments(clbl.Tok, ((Method)clbl).Attributes, module);
 8985717          } else if (clbl is IteratorDecl) {
 0718            body = ((IteratorDecl)clbl).Body;
 0719            CheckForFuelAdjustments(clbl.Tok, ((IteratorDecl)clbl).Attributes, module);
 12920720          } else if (clbl is Function) {
 6460721            CheckForFuelAdjustments(clbl.Tok, ((Function)clbl).Attributes, module);
 6460722            var c = new FuelAdjustment_Visitor(this);
 6460723            var bodyExpr = ((Function)clbl).Body;
 12920724            if (bodyExpr != null) {
 6460725              c.Visit(bodyExpr, new FuelAdjustment_Context(module));
 6460726            }
 6460727          }
 728
 11510729          if (body != null) {
 2525730            var c = new FuelAdjustment_Visitor(this);
 2525731            c.Visit(body, new FuelAdjustment_Context(module));
 2525732          }
 8985733        }
 415734      }
 735
 415736      Type.DisableScopes();
 415737      CheckDupModuleNames(prog);
 738
 2490739      foreach (var module in prog.Modules()) {
 21165740        foreach (var rewriter in rewriters) {
 6640741          rewriter.PostResolve(module);
 6640742        }
 415743      }
 744
 21165745      foreach (var rewriter in rewriters) {
 6640746        rewriter.PostResolve(prog);
 6640747      }
 415748    }
 749
 750
 751
 415752    private void ResolveValuetypeDecls() {
 415753      moduleInfo = systemNameInfo;
 9960754      foreach (var valueTypeDecl in valuetypeDecls) {
 24900755        foreach (var kv in valueTypeDecl.Members) {
 6225756          if (kv.Value is Function function) {
 830757            ResolveFunctionSignature(function);
 830758            CallGraphBuilder.VisitFunction(function, reporter);
 5395759          } else if (kv.Value is Method method) {
 0760            ResolveMethodSignature(method);
 0761            CallGraphBuilder.VisitMethod(method, reporter);
 0762          }
 5395763        }
 2905764      }
 415765    }
 766
 767    /// <summary>
 768    /// Resolves the module definition.
 769    /// A return code of "false" is an indication of an error that may or may not have
 770    /// been reported in an error message. So, in order to figure out if m was successfully
 771    /// resolved, a caller has to check for both a change in error count and a "false"
 772    /// return value.
 773    /// </summary>
 830774    private bool ResolveModuleDefinition(ModuleDefinition m, ModuleSignature sig, bool isAnExport = false) {
 775      Contract.Requires(AllTypeConstraints.Count == 0);
 776      Contract.Ensures(AllTypeConstraints.Count == 0);
 777
 830778      sig.VisibilityScope.Augment(systemNameInfo.VisibilityScope);
 779      // make sure all imported modules were successfully resolved
 4980780      foreach (var d in m.TopLevelDecls) {
 830781        if (d is AliasModuleDecl || d is AbstractModuleDecl) {
 782          ModuleSignature importSig;
 0783          if (d is AliasModuleDecl) {
 0784            var alias = (AliasModuleDecl)d;
 0785            importSig = alias.TargetQId.Root != null ? alias.TargetQId.Root.Signature : alias.Signature;
 0786          } else {
 0787            importSig = ((AbstractModuleDecl)d).OriginalSignature;
 0788          }
 789
 0790          if (importSig.ModuleDef == null || !importSig.ModuleDef.SuccessfullyResolved) {
 0791            if (!m.IsEssentiallyEmptyModuleBody()) {
 792              // say something only if this will cause any testing to be omitted
 0793              reporter.Error(MessageSource.Resolver, d,
 0794                "not resolving module '{0}' because there were errors in resolving its import '{1}'", m.Name, d.Name);
 0795            }
 796
 0797            return false;
 798          }
 830799        } else if (d is LiteralModuleDecl) {
 0800          var nested = (LiteralModuleDecl)d;
 0801          if (!nested.ModuleDef.SuccessfullyResolved) {
 0802            if (!m.IsEssentiallyEmptyModuleBody()) {
 803              // say something only if this will cause any testing to be omitted
 0804              reporter.Error(MessageSource.Resolver, nested,
 0805                "not resolving module '{0}' because there were errors in resolving its nested module '{1}'", m.Name,
 0806                nested.Name);
 0807            }
 808
 0809            return false;
 810          }
 0811        }
 830812      }
 813
 814      // resolve
 830815      var oldModuleInfo = moduleInfo;
 830816      moduleInfo = MergeSignature(sig, systemNameInfo);
 830817      Type.PushScope(moduleInfo.VisibilityScope);
 830818      ResolveOpenedImports(moduleInfo, m, useCompileSignatures, this); // opened imports do not persist
 830819      var datatypeDependencies = new Graph<IndDatatypeDecl>();
 830820      var codatatypeDependencies = new Graph<CoDatatypeDecl>();
 830821      var allDeclarations = ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(m.TopLevelDecls).ToList();
 830822      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 830823      ResolveTopLevelDecls_Signatures(m, sig, allDeclarations, datatypeDependencies, codatatypeDependencies);
 830824      Contract.Assert(AllTypeConstraints.Count == 0); // signature resolution does not add any type constraints
 825
 830826      scope.PushMarker();
 830827      scope.AllowInstance = false;
 830828      ResolveAttributes(m, new ResolutionContext(new NoContext(m.EnclosingModule), false), true); // Must follow Resolve
 830829      scope.PopMarker();
 830
 1660831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 830832        ResolveTopLevelDecls_Core(allDeclarations, datatypeDependencies, codatatypeDependencies, m.Name, isAnExport);
 830833      }
 834
 830835      Type.PopScope(moduleInfo.VisibilityScope);
 830836      moduleInfo = oldModuleInfo;
 830837      return true;
 830838    }
 839
 840    // Resolve the exports and detect cycles.
 415841    private void ResolveModuleExport(LiteralModuleDecl literalDecl, ModuleSignature sig) {
 415842      ModuleDefinition m = literalDecl.ModuleDef;
 415843      literalDecl.DefaultExport = sig;
 415844      Graph<ModuleExportDecl> exportDependencies = new Graph<ModuleExportDecl>();
 2490845      foreach (TopLevelDecl toplevel in m.TopLevelDecls) {
 415846        if (toplevel is ModuleExportDecl) {
 0847          ModuleExportDecl d = (ModuleExportDecl)toplevel;
 0848          exportDependencies.AddVertex(d);
 0849          foreach (IToken s in d.Extends) {
 850            ModuleExportDecl extend;
 0851            if (sig.ExportSets.TryGetValue(s.val, out extend)) {
 0852              d.ExtendDecls.Add(extend);
 0853              exportDependencies.AddEdge(d, extend);
 0854            } else {
 0855              reporter.Error(MessageSource.Resolver, s, s.val + " must be an export of " + m.Name + " to be extended");
 0856            }
 0857          }
 0858        }
 415859      }
 860
 861      // detect cycles in the extend
 415862      var cycleError = false;
 1245863      foreach (var cycle in exportDependencies.AllCycles()) {
 0864        ReportCycleError(cycle, m => m.tok, m => m.Name, "module export contains a cycle");
 0865        cycleError = true;
 0866      }
 867
 415868      if (cycleError) {
 0869        return;
 870      } // give up on trying to resolve anything else
 871
 872      // fill in the exports for the extends.
 415873      List<ModuleExportDecl> sortedExportDecls = exportDependencies.TopologicallySortedComponents();
 415874      ModuleExportDecl defaultExport = null;
 875      TopLevelDecl defaultClass;
 876
 415877      sig.TopLevels.TryGetValue("_default", out defaultClass);
 415878      Contract.Assert(defaultClass is ClassDecl);
 415879      Contract.Assert(((ClassDecl)defaultClass).IsDefaultClass);
 415880      defaultClass.AddVisibilityScope(m.VisibilityScope, true);
 881
 1245882      foreach (var d in sortedExportDecls) {
 883
 0884        defaultClass.AddVisibilityScope(d.ThisScope, true);
 885
 0886        foreach (var eexports in d.ExtendDecls.Select(e => e.Exports)) {
 0887          d.Exports.AddRange(eexports);
 0888        }
 889
 0890        if (d.ExtendDecls.Count == 0 && d.Exports.Count == 0) {
 891          // This is an empty export.  This is allowed, but unusual.  It could pop up, for example, if
 892          // someone temporary comments out everything that the export set provides/reveals.  However,
 893          // if the name of the export set coincides with something else that's declared at the top
 894          // level of the module, then this export declaration is more likely an error--the user probably
 895          // forgot the "provides" or "reveals" keyword.
 896          Dictionary<string, MemberDecl> members;
 897          MemberDecl member;
 898          // Top-level functions and methods are actually recorded as members of the _default class.  We look up the
 899          // export-set name there.  If the export-set name happens to coincide with some other top-level declaration,
 900          // then an error will already have been produced ("duplicate name of top-level declaration").
 0901          if (classMembers.TryGetValue((ClassDecl)defaultClass, out members) &&
 0902              members.TryGetValue(d.Name, out member)) {
 0903            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, d.tok,
 0904              "note, this export set is empty (did you perhaps forget the 'provides' or 'reveals' keyword?)");
 0905          }
 0906        }
 907
 0908        foreach (ExportSignature export in d.Exports) {
 909
 910          // check to see if it is a datatype or a member or
 911          // static function or method in the enclosing module or its imports
 912          TopLevelDecl tdecl;
 913          MemberDecl member;
 914          TopLevelDecl cldecl;
 915
 0916          Declaration decl = null;
 0917          string name = export.Id;
 918
 0919          if (export.ClassId != null) {
 0920            if (!sig.TopLevels.TryGetValue(export.ClassId, out cldecl)) {
 0921              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a top-level type declaration",
 0922                export.ClassId);
 0923              continue;
 924            }
 925
 0926            if (cldecl is ClassDecl && ((ClassDecl)cldecl).NonNullTypeDecl != null) {
 927              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0928              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0929                export.ClassId);
 0930              continue;
 931            }
 932
 0933            if (cldecl is NonNullTypeDecl) {
 934              // cldecl was given syntactically like the name of a class, but here it's referring to the corresponding n
 0935              cldecl = cldecl.ViewAsClass;
 0936            }
 937
 0938            var mt = cldecl as TopLevelDeclWithMembers;
 0939            if (mt == null) {
 0940              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0941                export.ClassId);
 0942              continue;
 943            }
 944
 0945            var lmem = mt.Members.FirstOrDefault(l => l.Name == export.Id);
 0946            if (lmem == null) {
 0947              reporter.Error(MessageSource.Resolver, export.Tok, "No member '{0}' found in type '{1}'", export.Id,
 0948                export.ClassId);
 0949              continue;
 950            }
 951
 0952            decl = lmem;
 0953          } else if (sig.TopLevels.TryGetValue(name, out tdecl)) {
 0954            if (tdecl is ClassDecl && ((ClassDecl)tdecl).NonNullTypeDecl != null) {
 955              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0956              var nn = ((ClassDecl)tdecl).NonNullTypeDecl;
 0957              Contract.Assert(nn != null);
 0958              reporter.Error(MessageSource.Resolver, export.Tok,
 0959                export.Opaque
 0960                  ? "Type '{1}' can only be revealed, not provided"
 0961                  : "Types '{0}' and '{1}' are exported together, which is accomplished by revealing the name '{0}'",
 0962                nn.Name, name);
 0963              continue;
 964            }
 965
 966            // Member of the enclosing module
 0967            decl = tdecl;
 0968          } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 0969            decl = member;
 0970          } else if (sig.ExportSets.ContainsKey(name)) {
 0971            reporter.Error(MessageSource.Resolver, export.Tok,
 0972              "'{0}' is an export set and cannot be provided/revealed by another export set (did you intend to list it i
 0973              name);
 0974            continue;
 0975          } else {
 0976            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' must be a member of '{1}' to be exported", name,
 0977              m.Name);
 0978            continue;
 979          }
 980
 0981          if (!decl.CanBeExported()) {
 0982            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' is not a valid export of '{1}'", name, m.Name);
 0983            continue;
 984          }
 985
 0986          if (!export.Opaque && !decl.CanBeRevealed()) {
 0987            reporter.Error(MessageSource.Resolver, export.Tok,
 0988              "'{0}' cannot be revealed in an export. Use \"provides\" instead.", name);
 0989            continue;
 990          }
 991
 0992          export.Decl = decl;
 0993          if (decl is NonNullTypeDecl nntd) {
 0994            nntd.AddVisibilityScope(d.ThisScope, export.Opaque);
 0995            if (!export.Opaque) {
 0996              nntd.Class.AddVisibilityScope(d.ThisScope, export.Opaque);
 997              // add the anonymous constructor, if any
 0998              var anonymousConstructor = nntd.Class.Members.Find(mdecl => mdecl.Name == "_ctor");
 0999              if (anonymousConstructor != null) {
 01000                anonymousConstructor.AddVisibilityScope(d.ThisScope, false);
 01001              }
 01002            }
 01003          } else {
 01004            decl.AddVisibilityScope(d.ThisScope, export.Opaque);
 01005          }
 01006        }
 01007      }
 1008
 12451009      foreach (ModuleExportDecl decl in sortedExportDecls) {
 01010        if (decl.IsDefault) {
 01011          if (defaultExport == null) {
 01012            defaultExport = decl;
 01013          } else {
 01014            reporter.Error(MessageSource.Resolver, m.tok, "more than one default export set declared in module {0}",
 01015              m.Name);
 01016          }
 01017        }
 1018
 1019        // fill in export signature
 01020        ModuleSignature signature = decl.Signature;
 01021        if (signature != null) {
 01022          signature.ModuleDef = m;
 01023        }
 1024
 01025        foreach (var top in sig.TopLevels) {
 01026          if (!top.Value.CanBeExported() || !top.Value.IsVisibleInScope(signature.VisibilityScope)) {
 01027            continue;
 1028          }
 1029
 01030          if (!signature.TopLevels.ContainsKey(top.Key)) {
 01031            signature.TopLevels.Add(top.Key, top.Value);
 01032          }
 1033
 01034          if (top.Value is DatatypeDecl && top.Value.IsRevealedInScope(signature.VisibilityScope)) {
 01035            foreach (var ctor in ((DatatypeDecl)top.Value).Ctors) {
 01036              if (!signature.Ctors.ContainsKey(ctor.Name)) {
 01037                signature.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 01038              }
 01039            }
 01040          }
 01041        }
 1042
 01043        foreach (var mem in sig.StaticMembers.Where(t =>
 01044          t.Value.IsVisibleInScope(signature.VisibilityScope) && t.Value.CanBeExported())) {
 01045          if (!signature.StaticMembers.ContainsKey(mem.Key)) {
 01046            signature.StaticMembers.Add(mem.Key, (MemberDecl)mem.Value);
 01047          }
 01048        }
 01049      }
 1050
 1051      // set the default export set, if it exists
 4151052      if (defaultExport != null) {
 01053        literalDecl.DefaultExport = defaultExport.Signature;
 4151054      } else if (sortedExportDecls.Count > 0) {
 01055        literalDecl.DefaultExport = null;
 01056      }
 1057
 1058      // final pass to propagate visibility of exported imports
 4151059      var sigs = sortedExportDecls.Select(d => d.Signature).Concat1(sig);
 1060
 24901061      foreach (var s in sigs) {
 24901062        foreach (var decl in s.TopLevels) {
 4151063          if (decl.Value is ModuleDecl && !(decl.Value is ModuleExportDecl)) {
 01064            var modDecl = (ModuleDecl)decl.Value;
 01065            s.VisibilityScope.Augment(modDecl.AccessibleSignature().VisibilityScope);
 01066          }
 4151067        }
 4151068      }
 1069
 4151070      var exported = new HashSet<Tuple<Declaration, bool>>();
 1071
 1072      //some decls may not be set due to resolution errors
 12451073      foreach (var e in sortedExportDecls.SelectMany(e => e.Exports).Where(e => e.Decl != null)) {
 01074        var decl = e.Decl;
 01075        exported.Add(new Tuple<Declaration, bool>(decl, e.Opaque));
 01076        if (!e.Opaque && decl.CanBeRevealed()) {
 01077          exported.Add(new Tuple<Declaration, bool>(decl, true));
 01078          if (decl is NonNullTypeDecl nntd) {
 01079            exported.Add(new Tuple<Declaration, bool>(nntd.Class, true));
 01080          }
 01081        }
 1082
 01083        if (e.Opaque && (decl is DatatypeDecl || decl is TypeSynonymDecl)) {
 1084          // Datatypes and type synonyms are marked as _provided when they appear in any provided export.  If a
 1085          // declaration is never provided, then either it isn't visible outside the module at all or its whole
 1086          // definition is.  Datatype and type-synonym declarations undergo some inference from their definitions.
 1087          // Such inference should not be done for provided declarations, since different views of the module
 1088          // would then get different inferred properties.
 01089          decl.Attributes = new Attributes("_provided", new List<Expression>(), decl.Attributes);
 01090          reporter.Info(MessageSource.Resolver, decl.tok, "{:_provided}");
 01091        }
 01092      }
 1093
 4151094      Dictionary<RevealableTypeDecl, bool?> declScopes = new Dictionary<RevealableTypeDecl, bool?>();
 4151095      Dictionary<RevealableTypeDecl, bool?> modifies = new Dictionary<RevealableTypeDecl, bool?>();
 1096
 1097      //of all existing types, compute the minimum visibility of them for each exported declaration's
 1098      //body and signature
 12451099      foreach (var e in exported) {
 1100
 01101        declScopes.Clear();
 01102        modifies.Clear();
 1103
 01104        foreach (var typ in revealableTypes) {
 01105          declScopes.Add(typ, null);
 01106        }
 1107
 01108        foreach (var decl in sortedExportDecls) {
 01109          if (decl.Exports.Exists(ex => ex.Decl == e.Item1 && (e.Item2 || !ex.Opaque))) {
 1110            //if we are revealed, consider those exports where we are provided as well
 01111            var scope = decl.Signature.VisibilityScope;
 1112
 01113            foreach (var kv in declScopes) {
 01114              bool? isOpaque = kv.Value;
 01115              var typ = kv.Key;
 01116              if (!typ.AsTopLevelDecl.IsVisibleInScope(scope)) {
 01117                modifies[typ] = null;
 01118                continue;
 1119              }
 1120
 01121              if (isOpaque.HasValue && isOpaque.Value) {
 1122                //type is visible here, but known-opaque, so do nothing
 01123                continue;
 1124              }
 1125
 01126              modifies[typ] = !typ.AsTopLevelDecl.IsRevealedInScope(scope);
 01127            }
 1128
 01129            foreach (var kv in modifies) {
 01130              if (!kv.Value.HasValue) {
 01131                declScopes.Remove(kv.Key);
 01132              } else {
 01133                var exvis = declScopes[kv.Key];
 01134                if (exvis.HasValue) {
 01135                  declScopes[kv.Key] = exvis.Value || kv.Value.Value;
 01136                } else {
 01137                  declScopes[kv.Key] = kv.Value;
 01138                }
 01139              }
 01140            }
 1141
 01142            modifies.Clear();
 01143          }
 01144        }
 1145
 01146        VisibilityScope newscope = new VisibilityScope(e.Item1.Name);
 1147
 01148        foreach (var rt in declScopes) {
 01149          if (!rt.Value.HasValue) {
 01150            continue;
 1151          }
 1152
 01153          rt.Key.AsTopLevelDecl.AddVisibilityScope(newscope, rt.Value.Value);
 01154        }
 01155      }
 4151156    }
 1157
 1158    //check for export consistency by resolving internal modules
 1159    //this should be effect-free, as it only operates on clones
 4151160    private void CheckModuleExportConsistency(ModuleDefinition m) {
 4151161      var oldModuleInfo = moduleInfo;
 12451162      foreach (var exportDecl in m.TopLevelDecls.OfType<ModuleExportDecl>()) {
 1163
 01164        var prevErrors = reporter.Count(ErrorLevel.Error);
 1165
 01166        foreach (var export in exportDecl.Exports) {
 01167          if (export.Decl is MemberDecl member) {
 1168            // For classes and traits, the visibility test is performed on the corresponding non-null type
 01169            var enclosingType = member.EnclosingClass is ClassDecl cl && cl.NonNullTypeDecl != null
 01170              ? cl.NonNullTypeDecl
 01171              : member.EnclosingClass;
 01172            if (!enclosingType.IsVisibleInScope(exportDecl.Signature.VisibilityScope)) {
 01173              reporter.Error(MessageSource.Resolver, export.Tok,
 01174                "Cannot export type member '{0}' without providing its enclosing {1} '{2}'", member.Name,
 01175                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01176            } else if (member is Constructor &&
 01177                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01178              reporter.Error(MessageSource.Resolver, export.Tok,
 01179                "Cannot export constructor '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01180                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01181            } else if (member is Field && !(member is ConstantField) &&
 01182                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01183              reporter.Error(MessageSource.Resolver, export.Tok,
 01184                "Cannot export mutable field '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01185                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01186            }
 01187          }
 01188        }
 1189
 01190        var scope = exportDecl.Signature.VisibilityScope;
 01191        Cloner cloner = new ScopeCloner(scope);
 01192        var exportView = cloner.CloneModuleDefinition(m, m.NameNode);
 01193        if (Options.DafnyPrintExportedViews.Contains(exportDecl.FullName)) {
 01194          var wr = Options.OutputWriter;
 01195          wr.WriteLine("/* ===== export set {0}", exportDecl.FullName);
 01196          var pr = new Printer(wr, Options);
 01197          pr.PrintTopLevelDecls(exportView.TopLevelDecls, 0, null, null);
 01198          wr.WriteLine("*/");
 01199        }
 1200
 01201        if (reporter.Count(ErrorLevel.Error) != prevErrors) {
 01202          continue;
 1203        }
 1204
 01205        reporter = new ErrorReporterWrapper(reporter,
 01206          String.Format("Raised while checking export set {0}: ", exportDecl.Name));
 01207        var testSig = RegisterTopLevelDecls(exportView, true);
 1208        //testSig.Refines = refinementTransformer.RefinedSig;
 01209        ResolveModuleDefinition(exportView, testSig, true);
 01210        var wasError = reporter.Count(ErrorLevel.Error) > 0;
 01211        reporter = ((ErrorReporterWrapper)reporter).WrappedReporter;
 1212
 01213        if (wasError) {
 01214          reporter.Error(MessageSource.Resolver, exportDecl.tok, "This export set is not consistent: {0}", exportDecl.Na
 01215        }
 01216      }
 1217
 4151218      moduleInfo = oldModuleInfo;
 4151219    }
 1220
 1221    public class ModuleBindings {
 1222      private ModuleBindings parent;
 1223      private Dictionary<string, ModuleDecl> modules;
 1224      private Dictionary<string, ModuleBindings> bindings;
 1225
 16601226      public ModuleBindings(ModuleBindings p) {
 8301227        parent = p;
 8301228        modules = new Dictionary<string, ModuleDecl>();
 8301229        bindings = new Dictionary<string, ModuleBindings>();
 8301230      }
 1231
 4151232      public bool BindName(string name, ModuleDecl subModule, ModuleBindings b) {
 4151233        if (modules.ContainsKey(name)) {
 01234          return false;
 4151235        } else {
 4151236          modules.Add(name, subModule);
 4151237          bindings.Add(name, b);
 4151238          return true;
 1239        }
 4151240      }
 1241
 01242      public bool TryLookup(IToken name, out ModuleDecl m) {
 1243        Contract.Requires(name != null);
 01244        return TryLookupFilter(name, out m, l => true);
 01245      }
 1246
 01247      public bool TryLookupFilter(IToken name, out ModuleDecl m, Func<ModuleDecl, bool> filter) {
 1248        Contract.Requires(name != null);
 01249        if (modules.TryGetValue(name.val, out m) && filter(m)) {
 01250          return true;
 01251        } else if (parent != null) {
 01252          return parent.TryLookupFilter(name, out m, filter);
 01253        } else {
 01254          return false;
 1255        }
 01256      }
 1257
 1258      public IEnumerable<ModuleDecl> ModuleList {
 01259        get { return modules.Values; }
 1260      }
 1261
 01262      public ModuleBindings SubBindings(string name) {
 01263        ModuleBindings v = null;
 01264        bindings.TryGetValue(name, out v);
 01265        return v;
 01266      }
 1267    }
 1268
 4151269    private ModuleBindings BindModuleNames(ModuleDefinition moduleDecl, ModuleBindings parentBindings) {
 4151270      var bindings = new ModuleBindings(parentBindings);
 1271
 1272      // moduleDecl.PrefixNamedModules is a list of pairs like:
 1273      //     A.B.C  ,  module D { ... }
 1274      // We collect these according to the first component of the prefix, like so:
 1275      //     "A"   ->   (A.B.C  ,  module D { ... })
 4151276      var prefixNames = new Dictionary<string, List<Tuple<List<IToken>, LiteralModuleDecl>>>();
 12451277      foreach (var tup in moduleDecl.PrefixNamedModules) {
 01278        var id = tup.Item1[0].val;
 1279        List<Tuple<List<IToken>, LiteralModuleDecl>> prev;
 01280        if (!prefixNames.TryGetValue(id, out prev)) {
 01281          prev = new List<Tuple<List<IToken>, LiteralModuleDecl>>();
 01282        }
 1283
 01284        prev.Add(tup);
 01285        prefixNames[id] = prev;
 01286      }
 1287
 4151288      moduleDecl.PrefixNamedModules.Clear();
 1289
 1290      // First, register all literal modules, and transferring their prefix-named modules downwards
 24901291      foreach (var tld in moduleDecl.TopLevelDecls) {
 4151292        if (tld is LiteralModuleDecl) {
 01293          var subdecl = (LiteralModuleDecl)tld;
 1294          // Transfer prefix-named modules downwards into the sub-module
 1295          List<Tuple<List<IToken>, LiteralModuleDecl>> prefixModules;
 01296          if (prefixNames.TryGetValue(subdecl.Name, out prefixModules)) {
 01297            prefixNames.Remove(subdecl.Name);
 01298            prefixModules = prefixModules.ConvertAll(ShortenPrefix);
 01299          } else {
 01300            prefixModules = null;
 01301          }
 1302
 01303          BindModuleName_LiteralModuleDecl(subdecl, prefixModules, bindings);
 01304        }
 4151305      }
 1306
 1307      // Next, add new modules for any remaining entries in "prefixNames".
 12451308      foreach (var entry in prefixNames) {
 01309        var name = entry.Key;
 01310        var prefixNamedModules = entry.Value;
 01311        var tok = prefixNamedModules.First().Item1[0];
 01312        var modDef = new ModuleDefinition(tok.ToRange(), new Name(tok.ToRange(), name), new List<IToken>(), false, false
 01313          true, true);
 1314        // Every module is expected to have a default class, so we create and add one now
 01315        var defaultClass = new DefaultClassDecl(modDef, new List<MemberDecl>());
 01316        modDef.TopLevelDecls.Add(defaultClass);
 1317        // Add the new module to the top-level declarations of its parent and then bind its names as usual
 01318        var subdecl = new LiteralModuleDecl(modDef, moduleDecl);
 01319        moduleDecl.TopLevelDecls.Add(subdecl);
 01320        BindModuleName_LiteralModuleDecl(subdecl, prefixNamedModules.ConvertAll(ShortenPrefix), bindings);
 01321      }
 1322
 1323      // Finally, go through import declarations (that is, AbstractModuleDecl's and AliasModuleDecl's).
 24901324      foreach (var tld in moduleDecl.TopLevelDecls) {
 4151325        if (tld is AbstractModuleDecl || tld is AliasModuleDecl) {
 01326          var subdecl = (ModuleDecl)tld;
 01327          if (bindings.BindName(subdecl.Name, subdecl, null)) {
 1328            // the add was successful
 01329          } else {
 1330            // there's already something with this name
 1331            ModuleDecl prevDecl;
 01332            var yes = bindings.TryLookup(subdecl.tok, out prevDecl);
 01333            Contract.Assert(yes);
 01334            if (prevDecl is AbstractModuleDecl || prevDecl is AliasModuleDecl) {
 01335              reporter.Error(MessageSource.Resolver, subdecl.tok, "Duplicate name of import: {0}", subdecl.Name);
 01336            } else if (tld is AliasModuleDecl importDecl && importDecl.Opened && importDecl.TargetQId.Path.Count == 1 &&
 01337                       importDecl.Name == importDecl.TargetQId.rootName()) {
 01338              importDecl.ShadowsLiteralModule = true;
 01339            } else {
 01340              reporter.Error(MessageSource.Resolver, subdecl.tok,
 01341                "Import declaration uses same name as a module in the same scope: {0}", subdecl.Name);
 01342            }
 01343          }
 01344        }
 4151345      }
 1346
 4151347      return bindings;
 4151348    }
 1349
 01350    private Tuple<List<IToken>, LiteralModuleDecl> ShortenPrefix(Tuple<List<IToken>, LiteralModuleDecl> tup) {
 1351      Contract.Requires(tup.Item1.Count != 0);
 01352      var rest = tup.Item1.GetRange(1, tup.Item1.Count - 1);
 01353      return new Tuple<List<IToken>, LiteralModuleDecl>(rest, tup.Item2);
 01354    }
 1355
 1356    private void BindModuleName_LiteralModuleDecl(LiteralModuleDecl litmod,
 01357      List<Tuple<List<IToken>, LiteralModuleDecl>> /*?*/ prefixModules, ModuleBindings parentBindings) {
 1358      Contract.Requires(litmod != null);
 1359      Contract.Requires(parentBindings != null);
 1360
 1361      // Transfer prefix-named modules downwards into the sub-module
 01362      if (prefixModules != null) {
 01363        foreach (var tup in prefixModules) {
 01364          if (tup.Item1.Count == 0) {
 01365            tup.Item2.ModuleDef.EnclosingModule =
 01366              litmod.ModuleDef; // change the parent, now that we have found the right parent module for the prefix-name
 01367            var sm = new LiteralModuleDecl(tup.Item2.ModuleDef,
 01368              litmod.ModuleDef); // this will create a ModuleDecl with the right parent
 01369            litmod.ModuleDef.TopLevelDecls.Add(sm);
 01370          } else {
 01371            litmod.ModuleDef.PrefixNamedModules.Add(tup);
 01372          }
 01373        }
 01374      }
 1375
 01376      var bindings = BindModuleNames(litmod.ModuleDef, parentBindings);
 01377      if (!parentBindings.BindName(litmod.Name, litmod, bindings)) {
 01378        reporter.Error(MessageSource.Resolver, litmod.tok, "Duplicate module name: {0}", litmod.Name);
 01379      }
 01380    }
 1381
 1382    private bool ResolveQualifiedModuleIdRootRefines(ModuleDefinition context, ModuleBindings bindings, ModuleQualifiedI
 01383      out ModuleDecl result) {
 01384      Contract.Assert(qid != null);
 01385      IToken root = qid.Path[0].StartToken;
 01386      result = null;
 01387      bool res = bindings.TryLookupFilter(root, out result, m => m.EnclosingModuleDefinition != context);
 01388      qid.Root = result;
 01389      return res;
 01390    }
 1391
 1392    // Find a matching module for the root of the QualifiedId, ignoring
 1393    // (a) the module (context) itself and (b) any local imports
 1394    // The latter is so that if one writes 'import A`E  import F = A`F' the second A does not
 1395    // resolve to the alias produced by the first import
 1396    private bool ResolveQualifiedModuleIdRootImport(AliasModuleDecl context, ModuleBindings bindings, ModuleQualifiedId 
 01397      out ModuleDecl result) {
 01398      Contract.Assert(qid != null);
 01399      IToken root = qid.Path[0].StartToken;
 01400      result = null;
 01401      bool res = bindings.TryLookupFilter(root, out result,
 01402        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01403      qid.Root = result;
 01404      return res;
 01405    }
 1406
 1407    private bool ResolveQualifiedModuleIdRootAbstract(AbstractModuleDecl context, ModuleBindings bindings, ModuleQualifi
 01408      out ModuleDecl result) {
 01409      Contract.Assert(qid != null);
 01410      IToken root = qid.Path[0].StartToken;
 01411      result = null;
 01412      bool res = bindings.TryLookupFilter(root, out result,
 01413        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01414      qid.Root = result;
 01415      return res;
 01416    }
 1417
 1418    private void ProcessDependenciesDefinition(ModuleDecl decl, ModuleDefinition m, ModuleBindings bindings,
 4151419      Graph<ModuleDecl> dependencies) {
 4151420      Contract.Assert(decl is LiteralModuleDecl);
 4151421      if (m.RefinementQId != null) {
 1422        ModuleDecl other;
 01423        bool res = ResolveQualifiedModuleIdRootRefines(((LiteralModuleDecl)decl).ModuleDef, bindings, m.RefinementQId, o
 01424        if (!res) {
 01425          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(),
 01426            $"module {m.RefinementQId.ToString()} named as refinement base does not exist");
 01427        } else if (other is LiteralModuleDecl && ((LiteralModuleDecl)other).ModuleDef == m) {
 01428          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(), "module cannot refine itself: {0}",
 01429            m.RefinementQId.ToString());
 01430        } else {
 01431          Contract.Assert(other != null); // follows from postcondition of TryGetValue
 01432          dependencies.AddEdge(decl, other);
 01433        }
 01434      }
 1435
 24901436      foreach (var toplevel in m.TopLevelDecls) {
 4151437        if (toplevel is ModuleDecl) {
 01438          var d = (ModuleDecl)toplevel;
 01439          dependencies.AddEdge(decl, d);
 01440          var subbindings = bindings.SubBindings(d.Name);
 01441          ProcessDependencies(d, subbindings ?? bindings, dependencies);
 01442          if (!m.IsAbstract && d is AbstractModuleDecl && ((AbstractModuleDecl)d).QId.Root != null) {
 01443            reporter.Error(MessageSource.Resolver, d.tok,
 01444              "The abstract import named {0} (using :) may only be used in an abstract module declaration",
 01445              d.Name);
 01446          }
 01447        }
 4151448      }
 4151449    }
 1450
 4151451    private void ProcessDependencies(ModuleDecl moduleDecl, ModuleBindings bindings, Graph<ModuleDecl> dependencies) {
 4151452      dependencies.AddVertex(moduleDecl);
 8301453      if (moduleDecl is LiteralModuleDecl) {
 4151454        ProcessDependenciesDefinition(moduleDecl, ((LiteralModuleDecl)moduleDecl).ModuleDef, bindings, dependencies);
 4151455      } else if (moduleDecl is AliasModuleDecl) {
 01456        var alias = moduleDecl as AliasModuleDecl;
 1457        ModuleDecl root;
 1458        // TryLookupFilter works outward, looking for a match to the filter for
 1459        // each enclosing module.
 01460        if (!ResolveQualifiedModuleIdRootImport(alias, bindings, alias.TargetQId, out root)) {
 1461          //        if (!bindings.TryLookupFilter(alias.TargetQId.rootToken(), out root, m => alias != m)
 01462          reporter.Error(MessageSource.Resolver, alias.tok, ModuleNotFoundErrorMessage(0, alias.TargetQId.Path));
 01463        } else {
 01464          dependencies.AddEdge(moduleDecl, root);
 01465        }
 01466      } else if (moduleDecl is AbstractModuleDecl) {
 01467        var abs = moduleDecl as AbstractModuleDecl;
 1468        ModuleDecl root;
 01469        if (!ResolveQualifiedModuleIdRootAbstract(abs, bindings, abs.QId, out root)) {
 1470          //if (!bindings.TryLookupFilter(abs.QId.rootToken(), out root,
 1471          //  m => abs != m && (((abs.EnclosingModuleDefinition == m.EnclosingModuleDefinition) && (abs.Exports.Count ==
 01472          reporter.Error(MessageSource.Resolver, abs.tok, ModuleNotFoundErrorMessage(0, abs.QId.Path));
 01473        } else {
 01474          dependencies.AddEdge(moduleDecl, root);
 01475        }
 01476      }
 4151477    }
 1478
 01479    private static string ModuleNotFoundErrorMessage(int i, List<Name> path, string tail = "") {
 1480      Contract.Requires(path != null);
 1481      Contract.Requires(0 <= i && i < path.Count);
 01482      return "module " + path[i].Value + " does not exist" +
 01483             (1 < path.Count
 01484               ? " (position " + i.ToString() + " in path " + Util.Comma(".", path, x => x.Value) + ")" + tail
 01485               : "");
 01486    }
 1487
 1488    private static bool EquivIfPresent<T1, T2>(Dictionary<T1, T2> dic, T1 key, T2 val)
 179701489      where T2 : class {
 1490      T2 val2;
 179701491      if (dic.TryGetValue(key, out val2)) {
 01492        return val.Equals(val2);
 1493      }
 1494
 179701495      return true;
 179701496    }
 1497
 8301498    public static ModuleSignature MergeSignature(ModuleSignature m, ModuleSignature system) {
 1499      Contract.Requires(m != null);
 1500      Contract.Requires(system != null);
 8301501      var info = new ModuleSignature();
 1502      // add the system-declared information, among which we know there are no duplicates
 852601503      foreach (var kv in system.TopLevels) {
 275901504        info.TopLevels.Add(kv.Key, kv.Value);
 275901505      }
 1506
 102301507      foreach (var kv in system.Ctors) {
 25801508        info.Ctors.Add(kv.Key, kv.Value);
 25801509      }
 1510
 24901511      foreach (var kv in system.StaticMembers) {
 01512        info.StaticMembers.Add(kv.Key, kv.Value);
 01513      }
 1514
 1515      // add for the module itself
 49801516      foreach (var kv in m.TopLevels) {
 8301517        if (info.TopLevels.TryGetValue(kv.Key, out var infoValue)) {
 01518          if (infoValue != kv.Value) {
 1519            // This only happens if one signature contains the name C as a class C (because it
 1520            // provides C) and the other signature contains the name C as a non-null type decl
 1521            // (because it reveals C and C?). The merge output will contain the non-null type decl
 1522            // for the key (and we expect the mapping "C? -> class C" to be placed in the
 1523            // merge output as well, by the end of this loop).
 01524            if (infoValue is ClassDecl) {
 01525              var cd = (ClassDecl)infoValue;
 01526              Contract.Assert(cd.NonNullTypeDecl == kv.Value);
 01527              info.TopLevels[kv.Key] = kv.Value;
 01528            } else if (kv.Value is ClassDecl) {
 01529              var cd = (ClassDecl)kv.Value;
 01530              Contract.Assert(cd.NonNullTypeDecl == infoValue);
 1531              // info.TopLevel[kv.Key] already has the right value
 01532            } else {
 01533              Contract.Assert(false); // unexpected
 01534            }
 1535
 01536            continue;
 1537          }
 01538        }
 1539
 8301540        info.TopLevels[kv.Key] = kv.Value;
 8301541      }
 1542
 24901543      foreach (var kv in m.Ctors) {
 01544        Contract.Assert(EquivIfPresent(info.Ctors, kv.Key, kv.Value));
 01545        info.Ctors[kv.Key] = kv.Value;
 01546      }
 1547
 564001548      foreach (var kv in m.StaticMembers) {
 179701549        Contract.Assert(EquivIfPresent(info.StaticMembers, kv.Key, kv.Value));
 179701550        info.StaticMembers[kv.Key] = kv.Value;
 179701551      }
 1552
 8301553      info.IsAbstract = m.IsAbstract;
 8301554      info.VisibilityScope = new VisibilityScope();
 8301555      info.VisibilityScope.Augment(m.VisibilityScope);
 8301556      info.VisibilityScope.Augment(system.VisibilityScope);
 8301557      return info;
 8301558    }
 1559
 1560    public static void ResolveOpenedImports(ModuleSignature sig, ModuleDefinition moduleDef, bool useCompileSignatures,
 8301561      Resolver resolver) {
 8301562      var declarations = sig.TopLevels.Values.ToList<TopLevelDecl>();
 8301563      var importedSigs = new HashSet<ModuleSignature>() { sig };
 1564
 8301565      var topLevelDeclReplacements = new List<TopLevelDecl>();
 877501566      foreach (var top in declarations) {
 284201567        if (top is ModuleDecl md && md.Opened) {
 01568          ResolveOpenedImportsWorker(sig, moduleDef, (ModuleDecl)top, importedSigs, useCompileSignatures, out var topLev
 01569          if (topLevelDeclReplacement != null) {
 01570            topLevelDeclReplacements.Add(topLevelDeclReplacement);
 01571          }
 01572        }
 284201573      }
 24901574      foreach (var topLevelDeclReplacement in topLevelDeclReplacements) {
 01575        if (sig.TopLevels.GetValueOrDefault(topLevelDeclReplacement.Name) is ModuleDecl moduleDecl) {
 01576          sig.ShadowedImportedModules[topLevelDeclReplacement.Name] = moduleDecl;
 01577        }
 01578        sig.TopLevels[topLevelDeclReplacement.Name] = topLevelDeclReplacement;
 01579      }
 1580
 16601581      if (resolver != null) {
 1582        //needed because ResolveOpenedImports is used statically for a refinement check
 8301583        if (sig.TopLevels["_default"] is AmbiguousTopLevelDecl) {
 01584          Contract.Assert(sig.TopLevels["_default"].WhatKind == "class");
 01585          var cl = new DefaultClassDecl(moduleDef, sig.StaticMembers.Values.ToList());
 01586          sig.TopLevels["_default"] = cl;
 01587          resolver.classMembers[cl] = cl.Members.ToDictionary(m => m.Name);
 01588        }
 8301589      }
 8301590    }
 1591
 01592    static TopLevelDecl ResolveAlias(TopLevelDecl dd) {
 01593      while (dd is AliasModuleDecl amd) {
 01594        dd = amd.TargetQId.Root;
 01595      }
 01596      return dd;
 01597    }
 1598
 1599    /// <summary>
 1600    /// Further populate "sig" with the accessible symbols from "im".
 1601    ///
 1602    /// Symbols declared locally in "moduleDef" take priority over any opened-import symbols, with one
 1603    /// exception:  for an "import opened M" where "M" contains a top-level symbol "M", unambiguously map the
 1604    /// name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mapping
 1605    /// to the caller, and let the caller remap the symbol after all opened imports have been processed.
 1606    /// </summary>
 1607    static void ResolveOpenedImportsWorker(ModuleSignature sig, ModuleDefinition moduleDef, ModuleDecl im, HashSet<Modul
 01608      bool useCompileSignatures, out TopLevelDecl topLevelDeclReplacement) {
 1609
 01610      topLevelDeclReplacement = null;
 01611      var s = GetSignatureExt(im.AccessibleSignature(useCompileSignatures), useCompileSignatures);
 1612
 01613      if (importedSigs.Contains(s)) {
 01614        return; // we've already got these declarations
 1615      }
 1616
 01617      importedSigs.Add(s);
 1618
 1619      // top-level declarations:
 01620      foreach (var kv in s.TopLevels) {
 01621        if (!kv.Value.CanBeExported()) {
 01622          continue;
 1623        }
 1624
 01625        if (!sig.TopLevels.TryGetValue(kv.Key, out var d)) {
 01626          sig.TopLevels.Add(kv.Key, kv.Value);
 01627        } else if (d.EnclosingModuleDefinition == moduleDef) {
 01628          if (kv.Value.EnclosingModuleDefinition.DafnyName != kv.Key) {
 1629            // declarations in the importing module take priority over opened-import declarations
 01630          } else {
 1631            // As an exception to the rule, for an "import opened M" that contains a top-level symbol "M", unambiguously
 1632            // name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mappi
 1633            // the caller, and let the caller remap the symbol after all opened imports have been processed.
 01634            topLevelDeclReplacement = kv.Value;
 01635          }
 01636        } else {
 01637          bool unambiguous = false;
 1638          // keep just one if they normalize to the same entity
 01639          if (d == kv.Value) {
 01640            unambiguous = true;
 01641          } else if (d is ModuleDecl || kv.Value is ModuleDecl) {
 01642            var dd = ResolveAlias(d);
 01643            var dk = ResolveAlias(kv.Value);
 01644            unambiguous = dd == dk;
 01645          } else {
 1646            // It's okay if "d" and "kv.Value" denote the same type. This can happen, for example,
 1647            // if both are type synonyms for "int".
 01648            var scope = Type.GetScope();
 01649            if (d.IsVisibleInScope(scope) && kv.Value.IsVisibleInScope(scope)) {
 01650              var dType = UserDefinedType.FromTopLevelDecl(d.tok, d);
 01651              var vType = UserDefinedType.FromTopLevelDecl(kv.Value.tok, kv.Value);
 01652              unambiguous = dType.Equals(vType, true);
 01653            }
 01654          }
 01655          if (!unambiguous) {
 01656            sig.TopLevels[kv.Key] = AmbiguousTopLevelDecl.Create(moduleDef, d, kv.Value);
 01657          }
 01658        }
 01659      }
 1660
 1661      // constructors:
 01662      foreach (var kv in s.Ctors) {
 01663        if (sig.Ctors.TryGetValue(kv.Key, out var pair)) {
 1664          // The same ctor can be imported from two different imports (e.g "diamond" imports), in which case,
 1665          // they are not duplicates.
 01666          if (!Object.ReferenceEquals(kv.Value.Item1, pair.Item1)) {
 1667            // mark it as a duplicate
 01668            sig.Ctors[kv.Key] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 01669          }
 01670        } else {
 1671          // add new
 01672          sig.Ctors.Add(kv.Key, kv.Value);
 01673        }
 01674      }
 1675
 1676      // static members:
 01677      foreach (var kv in s.StaticMembers) {
 01678        if (!kv.Value.CanBeExported()) {
 01679          continue;
 1680        }
 1681
 01682        if (sig.StaticMembers.TryGetValue(kv.Key, out var md)) {
 01683          sig.StaticMembers[kv.Key] = AmbiguousMemberDecl.Create(moduleDef, md, kv.Value);
 01684        } else {
 1685          // add new
 01686          sig.StaticMembers.Add(kv.Key, kv.Value);
 01687        }
 01688      }
 01689    }
 1690
 12451691    ModuleSignature RegisterTopLevelDecls(ModuleDefinition moduleDef, bool useImports) {
 1692      Contract.Requires(moduleDef != null);
 12451693      var sig = new ModuleSignature();
 12451694      sig.ModuleDef = moduleDef;
 12451695      sig.IsAbstract = moduleDef.IsAbstract;
 12451696      sig.VisibilityScope = new VisibilityScope();
 12451697      sig.VisibilityScope.Augment(moduleDef.VisibilityScope);
 1698
 12451699      List<TopLevelDecl> declarations = moduleDef.TopLevelDecls;
 1700
 1701      // This is solely used to detect duplicates amongst the various e
 12451702      Dictionary<string, TopLevelDecl> toplevels = new Dictionary<string, TopLevelDecl>();
 1703      // Now add the things present
 12451704      var anonymousImportCount = 0;
 451201705      foreach (TopLevelDecl d in declarations) {
 137951706        Contract.Assert(d != null);
 1707
 246851708        if (d is RevealableTypeDecl) {
 108901709          revealableTypes.Add((RevealableTypeDecl)d);
 108901710        }
 1711
 1712        // register the class/datatype/module name
 137951713        {
 137951714          TopLevelDecl registerThisDecl = null;
 137951715          string registerUnderThisName = null;
 137951716          if (d is ModuleExportDecl export) {
 01717            if (sig.ExportSets.ContainsKey(d.Name)) {
 01718              reporter.Error(MessageSource.Resolver, d, "duplicate name of export set: {0}", d.Name);
 01719            } else {
 01720              sig.ExportSets[d.Name] = export;
 01721            }
 137951722          } else if (d is AliasModuleDecl importDecl && importDecl.ShadowsLiteralModule) {
 1723            // add under an anonymous name
 01724            registerThisDecl = d;
 01725            registerUnderThisName = string.Format("{0}#{1}", d.Name, anonymousImportCount);
 01726            anonymousImportCount++;
 137951727          } else if (toplevels.ContainsKey(d.Name)) {
 01728            reporter.Error(MessageSource.Resolver, d, "duplicate name of top-level declaration: {0}", d.Name);
 146251729          } else if (d is ClassDecl cl && cl.NonNullTypeDecl != null) {
 8301730            registerThisDecl = cl.NonNullTypeDecl;
 8301731            registerUnderThisName = d.Name;
 137951732          } else {
 129651733            registerThisDecl = d;
 129651734            registerUnderThisName = d.Name;
 129651735          }
 1736
 275901737          if (registerThisDecl != null) {
 137951738            toplevels[registerUnderThisName] = registerThisDecl;
 137951739            sig.TopLevels[registerUnderThisName] = registerThisDecl;
 137951740          }
 137951741        }
 137951742        if (d is ModuleDecl) {
 1743          // nothing to do
 193651744        } else if (d is TypeSynonymDecl) {
 1745          // nothing more to register
 137951746        } else if (d is NewtypeDecl || d is AbstractTypeDecl) {
 01747          var cl = (TopLevelDeclWithMembers)d;
 1748          // register the names of the type members
 01749          var members = new Dictionary<string, MemberDecl>();
 01750          classMembers.Add(cl, members);
 01751          RegisterMembers(moduleDef, cl, members);
 82251752        } else if (d is IteratorDecl) {
 01753          var iter = (IteratorDecl)d;
 1754
 01755          iter.Resolve(this);
 122551756        } else if (d is ClassDecl) {
 40301757          var cl = (ClassDecl)d;
 40301758          var preMemberErrs = reporter.Count(ErrorLevel.Error);
 1759
 1760          // register the names of the class members
 40301761          var members = new Dictionary<string, MemberDecl>();
 40301762          classMembers.Add(cl, members);
 40301763          RegisterMembers(moduleDef, cl, members);
 1764
 40301765          Contract.Assert(preMemberErrs != reporter.Count(ErrorLevel.Error) ||
 40301766                          !cl.Members.Except(members.Values).Any());
 1767
 48601768          if (cl.IsDefaultClass) {
 564001769            foreach (MemberDecl m in members.Values) {
 179701770              Contract.Assert(!m.HasStaticKeyword || m is ConstantField); // note, the IsStatic value isn't available ye
 359401771              if (m is Function || m is Method || m is ConstantField) {
 179701772                sig.StaticMembers[m.Name] = m;
 179701773              }
 1774
 179701775              if (toplevels.ContainsKey(m.Name)) {
 01776                reporter.Error(MessageSource.Resolver, m.tok,
 01777                  $"duplicate declaration for name {m.Name}");
 01778              }
 179701779            }
 8301780          }
 1781
 95151782        } else if (d is DatatypeDecl) {
 12901783          var dt = (DatatypeDecl)d;
 1784
 1785          // register the names of the constructors
 12901786          dt.ConstructorsByName = new();
 1787          // ... and of the other members
 12901788          var members = new Dictionary<string, MemberDecl>();
 12901789          classMembers.Add(dt, members);
 1790
 77401791          foreach (DatatypeCtor ctor in dt.Ctors) {
 12901792            if (ctor.Name.EndsWith("?")) {
 01793              reporter.Error(MessageSource.Resolver, ctor,
 01794                "a datatype constructor name is not allowed to end with '?'");
 12901795            } else if (dt.ConstructorsByName.ContainsKey(ctor.Name)) {
 01796              reporter.Error(MessageSource.Resolver, ctor, "Duplicate datatype constructor name: {0}", ctor.Name);
 12901797            } else {
 12901798              dt.ConstructorsByName.Add(ctor.Name, ctor);
 12901799              ctor.InheritVisibility(dt);
 1800
 1801              // create and add the query "method" (field, really)
 12901802              var queryName = ctor.NameNode.Append("?");
 12901803              var query = new DatatypeDiscriminator(ctor.RangeToken, queryName, SpecialField.ID.UseIdParam, "is_" + ctor
 12901804                ctor.IsGhost, Type.Bool, null);
 12901805              query.InheritVisibility(dt);
 12901806              query.EnclosingClass = dt; // resolve here
 12901807              members.Add(queryName.Value, query);
 12901808              ctor.QueryField = query;
 1809
 1810              // also register the constructor name globally
 1811              Tuple<DatatypeCtor, bool> pair;
 12901812              if (sig.Ctors.TryGetValue(ctor.Name, out pair)) {
 1813                // mark it as a duplicate
 01814                sig.Ctors[ctor.Name] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 12901815              } else {
 1816                // add new
 12901817                sig.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 12901818              }
 12901819            }
 12901820          }
 1821
 1822          // add deconstructors now (that is, after the query methods have been added)
 77401823          foreach (DatatypeCtor ctor in dt.Ctors) {
 12901824            var formalsUsedInThisCtor = new HashSet<string>();
 12901825            var duplicates = new HashSet<Formal>();
 107401826            foreach (var formal in ctor.Formals) {
 22901827              MemberDecl previousMember = null;
 22901828              var localDuplicate = false;
 45801829              if (formal.HasName) {
 22901830                if (members.TryGetValue(formal.Name, out previousMember)) {
 01831                  localDuplicate = formalsUsedInThisCtor.Contains(formal.Name);
 01832                  if (localDuplicate) {
 01833                    reporter.Error(MessageSource.Resolver, ctor,
 01834                      "Duplicate use of deconstructor name in the same constructor: {0}", formal.Name);
 01835                    duplicates.Add(formal);
 01836                  } else if (previousMember is DatatypeDestructor) {
 1837                    // this is okay, if the destructor has the appropriate type; this will be checked later, after type 
 01838                  } else {
 01839                    reporter.Error(MessageSource.Resolver, ctor,
 01840                      "Name of deconstructor is used by another member of the datatype: {0}", formal.Name);
 01841                  }
 01842                }
 1843
 22901844                formalsUsedInThisCtor.Add(formal.Name);
 22901845              }
 1846
 1847              DatatypeDestructor dtor;
 22901848              if (!localDuplicate && previousMember is DatatypeDestructor) {
 1849                // a destructor with this name already existed in (a different constructor in) the datatype
 01850                dtor = (DatatypeDestructor)previousMember;
 01851                dtor.AddAnotherEnclosingCtor(ctor, formal);
 22901852              } else {
 1853                // either the destructor has no explicit name, or this constructor declared another destructor with this
 22901854                dtor = new DatatypeDestructor(formal.RangeToken, ctor, formal, new Name(formal.RangeToken, formal.Name),
 22901855                  formal.IsGhost, formal.Type, null);
 22901856                dtor.InheritVisibility(dt);
 22901857                dtor.EnclosingClass = dt; // resolve here
 45801858                if (formal.HasName && !localDuplicate && previousMember == null) {
 1859                  // the destructor has an explict name and there was no member at all with this name before
 22901860                  members.Add(formal.Name, dtor);
 22901861                }
 22901862              }
 1863
 22901864              ctor.Destructors.Add(dtor);
 22901865            }
 1866
 38701867            foreach (var duplicate in duplicates) {
 01868              ctor.Formals.Remove(duplicate);
 01869            }
 12901870          }
 1871
 1872          // finally, add any additional user-defined members
 12901873          RegisterMembers(moduleDef, dt, members);
 41951874        } else {
 29051875          Contract.Assert(d is ValuetypeDecl);
 29051876        }
 137951877      }
 1878
 1879      // Now, for each class, register its possibly-null type
 451201880      foreach (TopLevelDecl d in declarations) {
 146251881        if ((d as ClassDecl)?.NonNullTypeDecl != null) {
 8301882          var name = d.Name + "?";
 1883          TopLevelDecl prev;
 8301884          if (toplevels.TryGetValue(name, out prev)) {
 01885            reporter.Error(MessageSource.Resolver, d,
 01886              "a module that already contains a top-level declaration '{0}' is not allowed to declare a {1} '{2}'",
 01887              name, d.WhatKind, d.Name);
 8301888          } else {
 8301889            toplevels[name] = d;
 8301890            sig.TopLevels[name] = d;
 8301891          }
 8301892        }
 137951893      }
 1894
 12451895      return sig;
 12451896    }
 1897
 1898    void RegisterMembers(ModuleDefinition moduleDef, TopLevelDeclWithMembers cl,
 53201899      Dictionary<string, MemberDecl> members) {
 1900      Contract.Requires(moduleDef != null);
 1901      Contract.Requires(cl != null);
 1902      Contract.Requires(members != null);
 1903
 853351904      foreach (MemberDecl m in cl.Members) {
 462501905        if (!members.ContainsKey(m.Name)) {
 231251906          members.Add(m.Name, m);
 231251907          if (m is Constructor) {
 01908            Contract.Assert(cl is ClassDecl); // the parser ensures this condition
 01909            if (cl is TraitDecl) {
 01910              reporter.Error(MessageSource.Resolver, m.tok, "a trait is not allowed to declare a constructor");
 01911            } else {
 01912              ((ClassDecl)cl).HasConstructor = true;
 01913            }
 231251914          } else if (m is ExtremePredicate || m is ExtremeLemma) {
 01915            var extraName = m.NameNode.Append("#");
 1916            MemberDecl extraMember;
 01917            var cloner = new Cloner();
 01918            var formals = new List<Formal>();
 1919            Type typeOfK;
 01920            if ((m is ExtremePredicate && ((ExtremePredicate)m).KNat) ||
 01921                (m is ExtremeLemma && ((ExtremeLemma)m).KNat)) {
 01922              typeOfK = new UserDefinedType(m.tok, "nat", (List<Type>)null);
 01923            } else {
 01924              typeOfK = new BigOrdinalType();
 01925            }
 1926
 01927            var k = new ImplicitFormal(m.tok, "_k", typeOfK, true, false);
 01928            reporter.Info(MessageSource.Resolver, m.tok, string.Format("_k: {0}", k.Type));
 01929            formals.Add(k);
 01930            if (m is ExtremePredicate extremePredicate) {
 01931              formals.AddRange(extremePredicate.Formals.ConvertAll(f => cloner.CloneFormal(f, false)));
 1932
 01933              List<TypeParameter> tyvars = extremePredicate.TypeArgs.ConvertAll(cloner.CloneTypeParam);
 1934
 1935              // create prefix predicate
 01936              extremePredicate.PrefixPredicate = new PrefixPredicate(extremePredicate.RangeToken, extraName, extremePred
 01937                tyvars, k, formals,
 01938                extremePredicate.Req.ConvertAll(cloner.CloneAttributedExpr),
 01939                extremePredicate.Reads.ConvertAll(cloner.CloneFrameExpr),
 01940                extremePredicate.Ens.ConvertAll(cloner.CloneAttributedExpr),
 01941                new Specification<Expression>(new List<Expression>() { new IdentifierExpr(extremePredicate.tok, k.Name) 
 01942                cloner.CloneExpr(extremePredicate.Body),
 01943                null,
 01944                extremePredicate);
 01945              extraMember = extremePredicate.PrefixPredicate;
 01946            } else {
 01947              var extremeLemma = (ExtremeLemma)m;
 1948              // _k has already been added to 'formals', so append the original formals
 01949              formals.AddRange(extremeLemma.Ins.ConvertAll(f => cloner.CloneFormal(f, false)));
 1950              // prepend _k to the given decreases clause
 01951              var decr = new List<Expression>();
 01952              decr.Add(new IdentifierExpr(extremeLemma.tok, k.Name));
 01953              decr.AddRange(extremeLemma.Decreases.Expressions.ConvertAll(cloner.CloneExpr));
 1954              // Create prefix lemma.  Note that the body is not cloned, but simply shared.
 1955              // For a greatest lemma, the postconditions are filled in after the greatest lemma's postconditions have b
 1956              // For a least lemma, the preconditions are filled in after the least lemma's preconditions have been reso
 01957              var req = extremeLemma is GreatestLemma
 01958                ? extremeLemma.Req.ConvertAll(cloner.CloneAttributedExpr)
 01959                : new List<AttributedExpression>();
 01960              var ens = extremeLemma is GreatestLemma
 01961                ? new List<AttributedExpression>()
 01962                : extremeLemma.Ens.ConvertAll(cloner.CloneAttributedExpr);
 01963              extremeLemma.PrefixLemma = new PrefixLemma(extremeLemma.RangeToken, extraName, extremeLemma.HasStaticKeywo
 01964                extremeLemma.TypeArgs.ConvertAll(cloner.CloneTypeParam), k, formals, extremeLemma.Outs.ConvertAll(f => c
 01965                req, cloner.CloneSpecFrameExpr(extremeLemma.Mod), ens,
 01966                new Specification<Expression>(decr, null),
 01967                null, // Note, the body for the prefix method will be created once the call graph has been computed and 
 01968                cloner.CloneAttributes(extremeLemma.Attributes), extremeLemma);
 01969              extraMember = extremeLemma.PrefixLemma;
 01970            }
 1971
 01972            extraMember.InheritVisibility(m, false);
 01973            members.Add(extraName.Value, extraMember);
 231251974          } else if (m is Function f && f.ByMethodBody != null) {
 01975            RegisterByMethod(f, cl);
 01976          }
 231251977        } else if (m is Constructor && !((Constructor)m).HasName) {
 01978          reporter.Error(MessageSource.Resolver, m, "More than one anonymous constructor");
 01979        } else {
 01980          reporter.Error(MessageSource.Resolver, m, "Duplicate member name: {0}", m.Name);
 01981        }
 231251982      }
 53201983    }
 1984
 01985    void RegisterByMethod(Function f, TopLevelDeclWithMembers cl) {
 1986      Contract.Requires(f != null && f.ByMethodBody != null);
 1987
 01988      var tok = f.ByMethodTok;
 01989      var resultVar = f.Result ?? new Formal(tok, "#result", f.ResultType, false, false, null);
 01990      var r = Expression.CreateIdentExpr(resultVar);
 01991      var receiver = f.IsStatic ? (Expression)new StaticReceiverExpr(tok, cl, true) : new ImplicitThisExpr(tok);
 01992      var fn = new FunctionCallExpr(tok, f.Name, receiver, tok, tok, f.Formals.ConvertAll(Expression.CreateIdentExpr));
 01993      var post = new AttributedExpression(new BinaryExpr(tok, BinaryExpr.Opcode.Eq, r, fn));
 01994      var method = new Method(f.RangeToken, f.NameNode, f.HasStaticKeyword, false, f.TypeArgs,
 01995        f.Formals, new List<Formal>() { resultVar },
 01996        f.Req, new Specification<FrameExpression>(new List<FrameExpression>(), null), new List<AttributedExpression>() {
 01997        f.ByMethodBody, f.Attributes, null, true);
 01998      Contract.Assert(f.ByMethodDecl == null);
 01999      method.InheritVisibility(f);
 02000      method.FunctionFromWhichThisIsByMethodDecl = f;
 02001      f.ByMethodDecl = method;
 02002    }
 2003
 2004    private ModuleSignature MakeAbstractSignature(ModuleSignature p, string Name, int Height,
 2005      Dictionary<ModuleDefinition, ModuleSignature> mods,
 02006      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2007      Contract.Requires(p != null);
 2008      Contract.Requires(Name != null);
 2009      Contract.Requires(mods != null);
 2010      Contract.Requires(compilationModuleClones != null);
 02011      var errCount = reporter.Count(ErrorLevel.Error);
 2012
 02013      var mod = new ModuleDefinition(RangeToken.NoToken, new Name(Name + ".Abs"), new List<IToken>(), true, true, null, 
 02014        false,
 02015        p.ModuleDef.IsToBeVerified, p.ModuleDef.IsToBeCompiled);
 02016      mod.Height = Height;
 02017      bool hasDefaultClass = false;
 02018      foreach (var kv in p.TopLevels) {
 02019        hasDefaultClass = kv.Value is DefaultClassDecl || hasDefaultClass;
 02020        if (!(kv.Value is NonNullTypeDecl)) {
 02021          var clone = CloneDeclaration(p.VisibilityScope, kv.Value, mod, mods, Name, compilationModuleClones);
 02022          mod.TopLevelDecls.Add(clone);
 02023        }
 02024      }
 2025
 02026      if (!hasDefaultClass) {
 02027        DefaultClassDecl cl = new DefaultClassDecl(mod, p.StaticMembers.Values.ToList());
 02028        mod.TopLevelDecls.Add(CloneDeclaration(p.VisibilityScope, cl, mod, mods, Name, compilationModuleClones));
 02029      }
 2030
 02031      var sig = RegisterTopLevelDecls(mod, true);
 02032      sig.Refines = p.Refines;
 02033      sig.CompileSignature = p;
 02034      sig.IsAbstract = p.IsAbstract;
 02035      mods.Add(mod, sig);
 02036      var good = ResolveModuleDefinition(mod, sig);
 02037      if (good && reporter.Count(ErrorLevel.Error) == errCount) {
 02038        mod.SuccessfullyResolved = true;
 02039      }
 2040
 02041      return sig;
 02042    }
 2043
 2044    TopLevelDecl CloneDeclaration(VisibilityScope scope, TopLevelDecl d, ModuleDefinition m,
 2045      Dictionary<ModuleDefinition, ModuleSignature> mods, string Name,
 02046      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2047      Contract.Requires(d != null);
 2048      Contract.Requires(m != null);
 2049      Contract.Requires(mods != null);
 2050      Contract.Requires(Name != null);
 2051      Contract.Requires(compilationModuleClones != null);
 2052
 02053      if (d is AbstractModuleDecl) {
 02054        var abs = (AbstractModuleDecl)d;
 02055        var sig = MakeAbstractSignature(abs.OriginalSignature, Name + "." + abs.Name, abs.Height, mods,
 02056          compilationModuleClones);
 02057        var a = new AbstractModuleDecl(abs.RangeToken, abs.QId, abs.NameNode, m, abs.Opened, abs.Exports);
 02058        a.Signature = sig;
 02059        a.OriginalSignature = abs.OriginalSignature;
 02060        return a;
 02061      } else {
 02062        return new AbstractSignatureCloner(scope).CloneDeclaration(d, m);
 2063      }
 02064    }
 2065
 2066    // Returns the resolved Module declaration corresponding to the qualified module id
 2067    // Requires the root to have been resolved
 2068    // Issues an error and returns null if the path is not valid
 02069    public ModuleDecl ResolveModuleQualifiedId(ModuleDecl root, ModuleQualifiedId qid, ErrorReporter reporter) {
 2070
 2071      Contract.Requires(qid != null);
 2072      Contract.Requires(qid.Path.Count > 0);
 2073
 02074      List<Name> Path = qid.Path;
 02075      ModuleDecl decl = root;
 2076      ModuleSignature p;
 02077      for (int k = 1; k < Path.Count; k++) {
 02078        if (decl is LiteralModuleDecl) {
 02079          p = ((LiteralModuleDecl)decl).DefaultExport;
 02080          if (p == null) {
 02081            reporter.Error(MessageSource.Resolver, Path[k],
 02082              ModuleNotFoundErrorMessage(k, Path, $" because {decl.Name} does not have a default export"));
 02083            return null;
 2084          }
 02085        } else {
 02086          p = decl.Signature;
 02087        }
 2088
 02089        var tld = p.TopLevels.GetValueOrDefault(Path[k].Value, null);
 02090        if (!(tld is ModuleDecl dd)) {
 02091          if (decl.Signature.ModuleDef == null) {
 02092            reporter.Error(MessageSource.Resolver, Path[k],
 02093              ModuleNotFoundErrorMessage(k, Path, " because of previous error"));
 02094          } else {
 02095            reporter.Error(MessageSource.Resolver, Path[k], ModuleNotFoundErrorMessage(k, Path));
 02096          }
 02097          return null;
 2098        }
 2099
 2100        // Any aliases along the qualified path ought to be already resolved,
 2101        // else the modules are not being resolved in the right order
 02102        if (dd is AliasModuleDecl amd) {
 02103          Contract.Assert(amd.Signature != null);
 02104        }
 02105        decl = dd;
 02106      }
 2107
 02108      return decl;
 02109    }
 2110
 2111
 2112    public bool ResolveExport(ModuleDecl alias, ModuleDefinition parent, ModuleQualifiedId qid,
 02113      List<IToken> Exports, out ModuleSignature p, ErrorReporter reporter) {
 2114      Contract.Requires(qid != null);
 2115      Contract.Requires(qid.Path.Count > 0);
 2116      Contract.Requires(Exports != null);
 2117
 02118      ModuleDecl root = qid.Root;
 02119      ModuleDecl decl = ResolveModuleQualifiedId(root, qid, reporter);
 02120      if (decl == null) {
 02121        p = null;
 02122        return false;
 2123      }
 02124      p = decl.Signature;
 02125      if (Exports.Count == 0) {
 02126        if (p.ExportSets.Count == 0) {
 02127          if (decl is LiteralModuleDecl) {
 02128            p = ((LiteralModuleDecl)decl).DefaultExport;
 02129          } else {
 2130            // p is OK
 02131          }
 02132        } else {
 02133          var m = p.ExportSets.GetValueOrDefault(decl.Name, null);
 02134          if (m == null) {
 2135            // no default view is specified.
 02136            reporter.Error(MessageSource.Resolver, qid.rootToken(), "no default export set declared in module: {0}", dec
 02137            return false;
 2138          }
 02139          p = m.AccessibleSignature();
 02140        }
 02141      } else {
 2142        ModuleExportDecl pp;
 02143        if (decl.Signature.ExportSets.TryGetValue(Exports[0].val, out pp)) {
 02144          p = pp.AccessibleSignature();
 02145        } else {
 02146          reporter.Error(MessageSource.Resolver, Exports[0], "no export set '{0}' in module '{1}'", Exports[0].val, decl
 02147          p = null;
 02148          return false;
 2149        }
 2150
 02151        foreach (IToken export in Exports.Skip(1)) {
 02152          if (decl.Signature.ExportSets.TryGetValue(export.val, out pp)) {
 02153            Contract.Assert(Object.ReferenceEquals(p.ModuleDef, pp.Signature.ModuleDef));
 02154            ModuleSignature merged = MergeSignature(p, pp.Signature);
 02155            merged.ModuleDef = pp.Signature.ModuleDef;
 02156            if (p.CompileSignature != null) {
 02157              Contract.Assert(pp.Signature.CompileSignature != null);
 02158              merged.CompileSignature = MergeSignature(p.CompileSignature, pp.Signature.CompileSignature);
 02159            } else {
 02160              Contract.Assert(pp.Signature.CompileSignature == null);
 02161            }
 02162            p = merged;
 02163          } else {
 02164            reporter.Error(MessageSource.Resolver, export, "no export set {0} in module {1}", export.val, decl.Name);
 02165            p = null;
 02166            return false;
 2167          }
 02168        }
 02169      }
 02170      return true;
 02171    }
 2172
 12452173    public void RevealAllInScope(List<TopLevelDecl> declarations, VisibilityScope scope) {
 451202174      foreach (TopLevelDecl d in declarations) {
 137952175        d.AddVisibilityScope(scope, false);
 191152176        if (d is TopLevelDeclWithMembers) {
 53202177          var cl = (TopLevelDeclWithMembers)d;
 853352178          foreach (var mem in cl.Members) {
 462502179            if (!mem.ScopeIsInherited) {
 231252180              mem.AddVisibilityScope(scope, false);
 231252181            }
 231252182          }
 53202183          var nnd = (cl as ClassDecl)?.NonNullTypeDecl;
 61502184          if (nnd != null) {
 8302185            nnd.AddVisibilityScope(scope, false);
 8302186          }
 53202187        }
 137952188      }
 12452189    }
 2190
 8302191    public void ResolveTopLevelDecls_Signatures(ModuleDefinition def, ModuleSignature sig, List<TopLevelDecl/*!*/>/*!*/ 
 2192      Contract.Requires(declarations != null);
 2193      Contract.Requires(datatypeDependencies != null);
 2194      Contract.Requires(codatatypeDependencies != null);
 8302195      RevealAllInScope(declarations, def.VisibilityScope);
 2196
 2197      /* Augment the scoping environment for the current module*/
 49802198      foreach (TopLevelDecl d in declarations) {
 8302199        if (d is ModuleDecl && !(d is ModuleExportDecl)) {
 02200          var decl = (ModuleDecl)d;
 02201          moduleInfo.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02202          sig.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02203        }
 8302204      }
 2205      /*if (sig.Refines != null) {
 2206        moduleInfo.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2207        sig.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2208      }*/
 2209
 8302210      var typeRedirectionDependencies = new Graph<RedirectingTypeDecl>();  // this concerns the type directions, not the
 49802211      foreach (TopLevelDecl d in declarations) {
 8302212        Contract.Assert(d != null);
 8302213        allTypeParameters.PushMarker();
 8302214        ResolveTypeParameters(d.TypeArgs, true, d);
 8302215        if (d is TypeSynonymDecl) {
 02216          var dd = (TypeSynonymDecl)d;
 02217          ResolveType(dd.tok, dd.Rhs, dd, ResolveTypeOptionEnum.AllowPrefix, dd.TypeArgs);
 02218          dd.Rhs.ForeachTypeComponent(ty => {
 02219            var s = ty.AsRedirectingType;
 02220            if (s != null && s != dd) {
 02221              typeRedirectionDependencies.AddEdge(dd, s);
 02222            }
 02223          });
 8302224        } else if (d is NewtypeDecl) {
 02225          var dd = (NewtypeDecl)d;
 02226          ResolveType(dd.tok, dd.BaseType, dd, ResolveTypeOptionEnum.DontInfer, null);
 02227          dd.BaseType.ForeachTypeComponent(ty => {
 02228            var s = ty.AsRedirectingType;
 02229            if (s != null && s != dd) {
 02230              typeRedirectionDependencies.AddEdge(dd, s);
 02231            }
 02232          });
 02233          ResolveClassMemberTypes(dd);
 8302234        } else if (d is IteratorDecl) {
 02235          ResolveIteratorSignature((IteratorDecl)d);
 8302236        } else if (d is ModuleDecl) {
 02237          var decl = (ModuleDecl)d;
 02238          if (!def.IsAbstract && decl is AliasModuleDecl am && decl.Signature.IsAbstract) {
 02239            reporter.Error(MessageSource.Resolver, am.TargetQId.rootToken(), "a compiled module ({0}) is not allowed to 
 02240          }
 8302241        } else if (d is DatatypeDecl) {
 02242          var dd = (DatatypeDecl)d;
 02243          ResolveCtorTypes(dd, datatypeDependencies, codatatypeDependencies);
 02244          ResolveClassMemberTypes(dd);
 8302245        } else {
 8302246          ResolveClassMemberTypes((TopLevelDeclWithMembers)d);
 8302247        }
 8302248        allTypeParameters.PopMarker();
 8302249      }
 2250
 2251      // Resolve the parent-trait types and fill in .ParentTraitHeads
 8302252      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 8302253      var parentRelation = new Graph<TopLevelDeclWithMembers>();
 49802254      foreach (TopLevelDecl d in declarations) {
 16602255        if (d is TopLevelDeclWithMembers cl) {
 8302256          ResolveParentTraitTypes(cl, parentRelation);
 8302257        }
 8302258      }
 2259      // Check for cycles among parent traits
 24902260      foreach (var cycle in parentRelation.AllCycles()) {
 02261        ReportCycleError(cycle, m => m.tok, m => m.Name, "trait definitions contain a cycle");
 02262      }
 16602263      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2264        // Register the trait members in the classes that inherit them
 49802265        foreach (TopLevelDecl d in declarations) {
 16602266          if (d is TopLevelDeclWithMembers cl) {
 8302267            RegisterInheritedMembers(cl);
 8302268          }
 8302269        }
 8302270      }
 16602271      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2272        // Now that all traits have been resolved, let classes inherit the trait members
 49802273        foreach (var d in declarations) {
 16602274          if (d is TopLevelDeclWithMembers cl) {
 8302275            InheritedTraitMembers(cl);
 8302276          }
 8302277        }
 8302278      }
 2279
 2280      // perform acyclicity test on type synonyms
 24902281      foreach (var cycle in typeRedirectionDependencies.AllCycles()) {
 02282        ReportCycleError(cycle, rtd => rtd.tok, rtd => rtd.Name, "cycle among redirecting types (newtypes, subset types,
 02283      }
 8302284    }
 2285
 02286    public static readonly List<NativeType> NativeTypes = new List<NativeType>() {
 02287      new NativeType("byte", 0, 0x100, 8, NativeType.Selection.Byte),
 02288      new NativeType("sbyte", -0x80, 0x80, 0, NativeType.Selection.SByte),
 02289      new NativeType("ushort", 0, 0x1_0000, 16, NativeType.Selection.UShort),
 02290      new NativeType("short", -0x8000, 0x8000, 0, NativeType.Selection.Short),
 02291      new NativeType("uint", 0, 0x1_0000_0000, 32, NativeType.Selection.UInt),
 02292      new NativeType("int", -0x8000_0000, 0x8000_0000, 0, NativeType.Selection.Int),
 02293      new NativeType("number", -0x1f_ffff_ffff_ffff, 0x20_0000_0000_0000, 0, NativeType.Selection.Number),  // JavaScrip
 02294      new NativeType("ulong", 0, new BigInteger(0x1_0000_0000) * new BigInteger(0x1_0000_0000), 64, NativeType.Selection
 02295      new NativeType("long", Int64.MinValue, 0x8000_0000_0000_0000, 0, NativeType.Selection.Long),
 02296    };
 2297
 2298    public void ResolveTopLevelDecls_Core(List<TopLevelDecl> declarations,
 2299      Graph<IndDatatypeDecl> datatypeDependencies, Graph<CoDatatypeDecl> codatatypeDependencies,
 12452300      string moduleName, bool isAnExport = false) {
 2301
 2302      Contract.Requires(declarations != null);
 2303      Contract.Requires(cce.NonNullElements(datatypeDependencies.GetVertices()));
 2304      Contract.Requires(cce.NonNullElements(codatatypeDependencies.GetVertices()));
 2305      Contract.Requires(AllTypeConstraints.Count == 0);
 2306
 2307      Contract.Ensures(AllTypeConstraints.Count == 0);
 2308
 12452309      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 2310
 2311      // ---------------------------------- Pass 0 ----------------------------------
 2312      // This pass:
 2313      // * resolves names, introduces (and may solve) type constraints
 2314      // * checks that all types were properly inferred
 2315      // * fills in .ResolvedOp fields
 2316      // * perform substitution for DefaultValueExpression's
 2317      // ----------------------------------------------------------------------------
 2318
 12452319      if (Options.Get(CommonOptionBag.TypeSystemRefresh)) {
 2320        // Resolve all names and infer types.
 02321        var preTypeResolver = new PreTypeResolver(this);
 02322        preTypeResolver.ResolveDeclarations(declarations, moduleName);
 2323
 02324        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02325          var u = new UnderspecificationDetector(this);
 02326          u.Check(declarations);
 02327        }
 2328
 02329        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02330          new PreTypeToTypeVisitor().VisitDeclarations(declarations);
 02331        }
 2332
 12452333      } else {
 2334        // Resolve all names and infer types. These two are done together, because name resolution depends on having typ
 2335        // and type inference depends on having resolved names.
 2336        // The task is first performed for (the constraints of) newtype declarations, (the constraints of) subset type d
 2337        // (the right-hand sides of) const declarations, because type resolution sometimes needs to know the base type o
 2338        // and needs to know the type of const fields. Doing these declarations increases the chances the right informat
 2339        // in time.
 2340        // Once the task is done for these newtype/subset-type/const parts, the task continues with everything else.
 12452341        ResolveNamesAndInferTypes(declarations, true);
 12452342        ResolveNamesAndInferTypes(declarations, false);
 12452343      }
 2344
 2345      // Check that all types have been determined. During this process, also fill in all .ResolvedOp fields.
 24902346      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 12452347        var checkTypeInferenceVisitor = new CheckTypeInferenceVisitor(this);
 12452348        checkTypeInferenceVisitor.VisitDeclarations(declarations);
 12452349      }
 2350
 2351      // Substitute for DefaultValueExpression's
 12452352      FillInDefaultValueExpressions();
 2353
 2354      // ---------------------------------- Pass 1 ----------------------------------
 2355      // This pass does the following:
 2356      // * desugar functions used in reads clauses
 2357      // * compute .BodySurrogate for body-less loops
 2358      // * discovers bounds
 2359      // * builds the module's call graph.
 2360      // * compute and checks ghosts (this makes use of bounds discovery, as done above)
 2361      // * for newtypes, figure out native types
 2362      // * for datatypes, check that shared destructors are in agreement in ghost matters
 2363      // * for functions and methods, determine tail recursion
 2364      // ----------------------------------------------------------------------------
 2365
 2366      // Discover bounds. These are needed later to determine if certain things are ghost or compiled,
 2367      // and thus this should be done before building the call graph.
 2368      // The BoundsDiscoveryVisitor also desugars FrameExpressions, so that bounds discovery can
 2369      // apply to the desugared versions.
 2370      // This pass also computes body surrogates for body-less loops, which is a bit like desugaring
 2371      // such loops.
 24902372      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 12452373        var boundsDiscoveryVisitor = new BoundsDiscoveryVisitor(reporter);
 12452374        boundsDiscoveryVisitor.VisitDeclarations(declarations);
 12452375      }
 2376
 24902377      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 12452378        CallGraphBuilder.Build(declarations, reporter);
 12452379      }
 2380
 2381      // Compute ghost interests, figure out native types, check agreement among datatype destructors, and determine tai
 24902382      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 112052383        foreach (TopLevelDecl d in declarations) {
 24902384          if (d is IteratorDecl) {
 02385            var iter = (IteratorDecl)d;
 02386            iter.SubExpressions.Iter(e => CheckExpression(e, this, iter));
 02387            if (iter.Body != null) {
 02388              ComputeGhostInterest(iter.Body, false, null, iter);
 02389              CheckExpression(iter.Body, this, iter);
 02390            }
 2391
 33202392          } else if (d is SubsetTypeDecl subsetTypeDecl) {
 8302393            Contract.Assert(subsetTypeDecl.Constraint != null);
 8302394            CheckExpression(subsetTypeDecl.Constraint, this, new CodeContextWrapper(subsetTypeDecl, true));
 8302395            subsetTypeDecl.ConstraintIsCompilable =
 8302396              ExpressionTester.CheckIsCompilable(Options, null, subsetTypeDecl.Constraint, new CodeContextWrapper(subset
 8302397            subsetTypeDecl.CheckedIfConstraintIsCompilable = true;
 2398
 8302399            if (subsetTypeDecl.Witness != null) {
 02400              CheckExpression(subsetTypeDecl.Witness, this, new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.Witnes
 02401              if (subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02402                var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WK
 02403                ExpressionTester.CheckIsCompilable(Options, this, subsetTypeDecl.Witness, codeContext);
 02404              }
 02405            }
 2406
 24902407          } else if (d is NewtypeDecl newtypeDecl) {
 02408            if (newtypeDecl.Var != null) {
 02409              Contract.Assert(newtypeDecl.Constraint != null);
 02410              CheckExpression(newtypeDecl.Constraint, this, new CodeContextWrapper(newtypeDecl, true));
 02411              if (newtypeDecl.Witness != null) {
 02412                CheckExpression(newtypeDecl.Witness, this, new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind =
 02413              }
 02414            }
 02415            if (newtypeDecl.Witness != null && newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02416              var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghos
 02417              ExpressionTester.CheckIsCompilable(Options, this, newtypeDecl.Witness, codeContext);
 02418            }
 2419
 02420            FigureOutNativeType(newtypeDecl);
 2421
 16602422          } else if (d is DatatypeDecl) {
 02423            var dd = (DatatypeDecl)d;
 02424            foreach (var member in classMembers[dd].Values) {
 02425              var dtor = member as DatatypeDestructor;
 02426              if (dtor != null) {
 02427                var rolemodel = dtor.CorrespondingFormals[0];
 02428                for (int i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 02429                  var other = dtor.CorrespondingFormals[i];
 02430                  if (rolemodel.IsGhost != other.IsGhost) {
 02431                    reporter.Error(MessageSource.Resolver, other,
 02432                      "shared destructors must agree on whether or not they are ghost, but '{0}' is {1} in constructor '
 02433                      rolemodel.Name,
 02434                      rolemodel.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[0].Name,
 02435                      other.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[i].Name);
 02436                  }
 02437                }
 02438              }
 02439            }
 02440            foreach (var ctor in dd.Ctors) {
 02441              CheckParameterDefaultValuesAreCompilable(ctor.Formals, dd);
 02442            }
 02443          }
 2444
 41502445          if (d is TopLevelDeclWithMembers cl) {
 16602446            ResolveClassMembers_Pass1(cl);
 16602447          }
 24902448        }
 12452449      }
 2450
 2451      // ---------------------------------- Pass 2 ----------------------------------
 2452      // This pass fills in various additional information.
 2453      // * Subset type in comprehensions have a compilable constraint
 2454      // * Postconditions and bodies of prefix lemmas
 2455      // * Compute postconditions and statement body of prefix lemmas
 2456      // * Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes req
 2457      // * Set the SccRepr field of codatatypes
 2458      // * Perform the guardedness check on co-datatypes
 2459      // * Do datatypes and type synonyms until a fixpoint is reached, same for functions and methods
 2460      // * Check that functions claiming to be abstemious really are
 2461      // * Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2462      // * Extreme predicate recursivity checks
 2463      // * Verify that subset constraints are compilable if necessary
 2464      // ----------------------------------------------------------------------------
 2465
 24902466      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2467        // fill in the postconditions and bodies of prefix lemmas
 12452468        FillInPostConditionsAndBodiesOfPrefixLemmas(declarations);
 12452469      }
 2470
 2471      // Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes requi
 37352472      foreach (var dtd in datatypeDependencies.TopologicallySortedComponents()) {
 02473        if (datatypeDependencies.GetSCCRepresentative(dtd) == dtd) {
 2474          // do the following check once per SCC, so call it on each SCC representative
 02475          SccStratosphereCheck(dtd, datatypeDependencies);
 02476          DetermineEqualitySupport(dtd, datatypeDependencies);
 02477        }
 02478      }
 2479
 2480      // Set the SccRepr field of codatatypes
 37352481      foreach (var repr in codatatypeDependencies.TopologicallySortedComponents()) {
 02482        foreach (var codt in codatatypeDependencies.GetSCC(repr)) {
 02483          codt.SscRepr = repr;
 02484        }
 02485      }
 2486
 24902487      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {  // because CheckCoCalls requires the given expression t
 2488        // Perform the guardedness check on co-datatypes
 424952489        foreach (var repr in ModuleDefinition.AllFunctionSCCs(declarations)) {
 129202490          var module = repr.EnclosingModule;
 129202491          bool dealsWithCodatatypes = false;
 775202492          foreach (var m in module.CallGraph.GetSCC(repr)) {
 129202493            var f = m as Function;
 129202494            if (f != null && f.ResultType.InvolvesCoDatatype) {
 02495              dealsWithCodatatypes = true;
 02496              break;
 2497            }
 129202498          }
 129202499          var coCandidates = new List<CoCallResolution.CoCallInfo>();
 129202500          var hasIntraClusterCallsInDestructiveContexts = false;
 775202501          foreach (var m in module.CallGraph.GetSCC(repr)) {
 129202502            var f = m as Function;
 258402503            if (f != null && f.Body != null) {
 129202504              var checker = new CoCallResolution(f, dealsWithCodatatypes);
 129202505              checker.CheckCoCalls(f.Body);
 129202506              coCandidates.AddRange(checker.FinalCandidates);
 129202507              hasIntraClusterCallsInDestructiveContexts |= checker.HasIntraClusterCallsInDestructiveContexts;
 129202508            } else if (f == null) {
 2509              // the SCC contains a method, which we always consider to be a destructive context
 02510              hasIntraClusterCallsInDestructiveContexts = true;
 02511            }
 129202512          }
 129202513          if (coCandidates.Count != 0) {
 02514            if (hasIntraClusterCallsInDestructiveContexts) {
 02515              foreach (var c in coCandidates) {
 02516                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsInDestructiveContext;
 02517              }
 02518            } else {
 02519              foreach (var c in coCandidates) {
 02520                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 02521                c.EnclosingCoConstructor.IsCoCall = true;
 02522                reporter.Info(MessageSource.Resolver, c.CandidateCall.tok, "co-recursive call");
 02523              }
 2524              // Finally, fill in the CoClusterTarget field
 2525              // Start by setting all the CoClusterTarget fields to CoRecursiveTargetAllTheWay.
 02526              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02527                var f = (Function)m;  // the cast is justified on account of that we allow co-recursive calls only in cl
 02528                f.CoClusterTarget = Function.CoCallClusterInvolvement.CoRecursiveTargetAllTheWay;
 02529              }
 2530              // Then change the field to IsMutuallyRecursiveTarget whenever we see a non-self recursive non-co-recursiv
 02531              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02532                var f = (Function)m;  // cast is justified just like above
 02533                foreach (var call in f.AllCalls) {
 02534                  if (call.CoCall != FunctionCallExpr.CoCallResolution.Yes && call.Function != f && ModuleDefinition.InS
 02535                    call.Function.CoClusterTarget = Function.CoCallClusterInvolvement.IsMutuallyRecursiveTarget;
 02536                  }
 02537                }
 02538              }
 02539            }
 02540          }
 129202541        }
 2542        // Inferred required equality support for datatypes and type synonyms, and for Function and Method signatures.
 2543        // First, do datatypes and type synonyms until a fixpoint is reached.
 2544        bool inferredSomething;
 12452545        do {
 12452546          inferredSomething = false;
 112052547          foreach (var d in declarations) {
 24902548            if (Attributes.Contains(d.Attributes, "_provided")) {
 2549              // Don't infer required-equality-support for the type parameters, since there are
 2550              // scopes that see the name of the declaration but not its body.
 24902551            } else if (d is DatatypeDecl) {
 02552              var dt = (DatatypeDecl)d;
 02553              foreach (var tp in dt.TypeArgs) {
 02554                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2555                  // here's our chance to infer the need for equality support
 02556                  foreach (var ctor in dt.Ctors) {
 02557                    foreach (var arg in ctor.Formals) {
 02558                      if (InferRequiredEqualitySupport(tp, arg.Type)) {
 02559                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02560                        inferredSomething = true;
 02561                        goto DONE_DT;  // break out of the doubly-nested loop
 2562                      }
 02563                    }
 02564                  }
 02565                DONE_DT:;
 02566                }
 02567              }
 33202568            } else if (d is TypeSynonymDecl) {
 8302569              var syn = (TypeSynonymDecl)d;
 37352570              foreach (var tp in syn.TypeArgs) {
 8302571                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2572                  // here's our chance to infer the need for equality support
 4152573                  if (InferRequiredEqualitySupport(tp, syn.Rhs)) {
 02574                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02575                    inferredSomething = true;
 02576                  }
 4152577                }
 4152578              }
 8302579            }
 24902580          }
 24902581        } while (inferredSomething);
 2582        // Now do it for Function and Method signatures.
 112052583        foreach (var d in declarations) {
 24902584          if (d is IteratorDecl) {
 02585            var iter = (IteratorDecl)d;
 02586            var done = false;
 02587            var nonnullIter = iter.NonNullTypeDecl;
 02588            Contract.Assert(nonnullIter.TypeArgs.Count == iter.TypeArgs.Count);
 02589            for (var i = 0; i < iter.TypeArgs.Count; i++) {
 02590              var tp = iter.TypeArgs[i];
 02591              var correspondingNonnullIterTypeParameter = nonnullIter.TypeArgs[i];
 02592              if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2593                // here's our chance to infer the need for equality support
 02594                foreach (var p in iter.Ins) {
 02595                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02596                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02597                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02598                    done = true;
 02599                    break;
 2600                  }
 02601                }
 02602                foreach (var p in iter.Outs) {
 02603                  if (done) {
 02604                    break;
 2605                  }
 2606
 02607                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02608                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02609                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02610                    break;
 2611                  }
 02612                }
 02613              }
 02614            }
 41502615          } else if (d is ClassDecl) {
 16602616            var cl = (ClassDecl)d;
 601352617            foreach (var member in cl.Members) {
 367702618              if (!member.IsGhost) {
 313052619                if (member is Function) {
 129202620                  var f = (Function)member;
 611702621                  foreach (var tp in f.TypeArgs) {
 149402622                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2623                      // here's our chance to infer the need for equality support
 74702624                      if (InferRequiredEqualitySupport(tp, f.ResultType)) {
 02625                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 74702626                      } else {
 871502627                        foreach (var p in f.Formals) {
 215802628                          if (InferRequiredEqualitySupport(tp, p.Type)) {
 02629                            tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02630                            break;
 2631                          }
 215802632                        }
 74702633                      }
 74702634                    }
 74702635                  }
 234352636                } else if (member is Method) {
 50502637                  var m = (Method)member;
 50502638                  bool done = false;
 151502639                  foreach (var tp in m.TypeArgs) {
 02640                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2641                      // here's our chance to infer the need for equality support
 02642                      foreach (var p in m.Ins) {
 02643                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02644                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02645                          done = true;
 02646                          break;
 2647                        }
 02648                      }
 02649                      foreach (var p in m.Outs) {
 02650                        if (done) {
 02651                          break;
 2652                        }
 2653
 02654                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02655                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02656                          break;
 2657                        }
 02658                      }
 02659                    }
 02660                  }
 50502661                }
 183852662              }
 183852663            }
 16602664          }
 24902665        }
 2666        // Check that functions claiming to be abstemious really are, and check that 'older' parameters are used only wh
 424952667        foreach (var fn in ModuleDefinition.AllFunctions(declarations)) {
 129202668          new Abstemious(reporter).Check(fn);
 129202669          CheckOlderParameters(fn);
 129202670        }
 2671        // Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2672        // Note that this check can only be done after determining which expressions are ghosts.
 112052673        foreach (var d in declarations) {
 99602674          for (var attr = d.Attributes; attr != null; attr = attr.Prev) {
 24902675            attr.Args.Iter(e => CheckTypeCharacteristics_Expr(e, true));
 16602676          }
 2677
 24902678          if (d is IteratorDecl) {
 02679            var iter = (IteratorDecl)d;
 02680            foreach (var p in iter.Ins) {
 02681              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02682            }
 02683            foreach (var p in iter.Outs) {
 02684              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02685            }
 02686            if (iter.Body != null) {
 02687              CheckTypeCharacteristics_Stmt(iter.Body, false);
 02688            }
 41502689          } else if (d is ClassDecl) {
 16602690            var cl = (ClassDecl)d;
 49802691            foreach (var parentTrait in cl.ParentTraits) {
 02692              CheckTypeCharacteristics_Type(cl.tok, parentTrait, false);
 02693            }
 24902694          } else if (d is DatatypeDecl) {
 02695            var dt = (DatatypeDecl)d;
 02696            foreach (var ctor in dt.Ctors) {
 02697              foreach (var p in ctor.Formals) {
 02698                CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02699              }
 02700            }
 16602701          } else if (d is TypeSynonymDecl) {
 8302702            var syn = (TypeSynonymDecl)d;
 8302703            CheckTypeCharacteristics_Type(syn.tok, syn.Rhs, false);
 16602704            if (!isAnExport) {
 8302705              if (syn.SupportsEquality && !syn.Rhs.SupportsEquality) {
 02706                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as supporting equality, but the RHS
 02707                  syn.Name, syn.Rhs);
 02708              }
 8302709              if (syn.Characteristics.IsNonempty && !syn.Rhs.IsNonempty) {
 02710                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as being nonempty, but the RHS type
 02711                  syn.Name, syn.Rhs);
 8302712              } else if (syn.Characteristics.HasCompiledValue && !syn.Rhs.HasCompilableValue) {
 02713                reporter.Error(MessageSource.Resolver, syn.tok,
 02714                  "type '{0}' declared as auto-initialization type, but the RHS type ({1}) does not support auto-initial
 02715              }
 8302716              if (syn.Characteristics.ContainsNoReferenceTypes && syn.Rhs.MayInvolveReferences) {
 02717                reporter.Error(MessageSource.Resolver, syn.tok,
 02718                  "type '{0}' declared as containing no reference types, but the RHS type ({1}) may contain reference ty
 02719              }
 8302720            }
 8302721          }
 2722
 33202723          if (d is RedirectingTypeDecl) {
 8302724            var rtd = (RedirectingTypeDecl)d;
 16602725            if (rtd.Constraint != null) {
 8302726              CheckTypeCharacteristics_Expr(rtd.Constraint, true);
 8302727            }
 8302728            if (rtd.Witness != null) {
 02729              CheckTypeCharacteristics_Expr(rtd.Witness, rtd.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 02730            }
 8302731          }
 2732
 41502733          if (d is TopLevelDeclWithMembers) {
 16602734            var cl = (TopLevelDeclWithMembers)d;
 601352735            foreach (var member in cl.Members) {
 188002736              if (member is Field) {
 4152737                var f = (Field)member;
 4152738                CheckTypeCharacteristics_Type(f.tok, f.Type, f.IsGhost);
 4152739                if (f is ConstantField cf && cf.Rhs != null) {
 02740                  CheckTypeCharacteristics_Expr(cf.Rhs, cf.IsGhost);
 02741                }
 313052742              } else if (member is Function) {
 129202743                var f = (Function)member;
 1391102744                foreach (var p in f.Formals) {
 334502745                  CheckTypeCharacteristics_Type(p.tok, p.Type, f.IsGhost || p.IsGhost);
 334502746                }
 258402747                if (f.Body != null) {
 129202748                  CheckTypeCharacteristics_Expr(f.Body, f.IsGhost);
 129202749                }
 230202750              } else if (member is Method) {
 50502751                var m = (Method)member;
 482402752                foreach (var p in m.Ins) {
 110302753                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 110302754                }
 341702755                foreach (var p in m.Outs) {
 63402756                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 63402757                }
 101002758                if (m.Body != null) {
 50502759                  CheckTypeCharacteristics_Stmt(m.Body, m.IsGhost);
 50502760                }
 50502761              }
 183852762            }
 16602763          }
 24902764        }
 2765        // Check that extreme predicates are not recursive with non-extreme-predicate functions (and only
 2766        // with extreme predicates of the same polarity), and
 2767        // check that greatest lemmas are not recursive with non-greatest-lemma methods.
 2768        // Also, check that the constraints of newtypes/subset-types do not depend on the type itself.
 2769        // And check that const initializers are not cyclic.
 12452770        var cycleErrorHasBeenReported = new HashSet<ICallable>();
 112052771        foreach (var d in declarations) {
 41502772          if (d is TopLevelDeclWithMembers { Members: var members }) {
 601352773            foreach (var member in members) {
 183852774              if (member is ExtremePredicate) {
 02775                var fn = (ExtremePredicate)member;
 2776                // Check here for the presence of any 'ensures' clauses, which are not allowed (because we're not sure
 2777                // of their soundness)
 02778                fn.Req.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02779                fn.Decreases.Expressions.ForEach(e => ExtremePredicateChecks(e, fn, CallingPosition.Positive));
 02780                fn.Reads.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02781                if (fn.Ens.Count != 0) {
 02782                  reporter.Error(MessageSource.Resolver, fn.Ens[0].E.tok, "a {0} is not allowed to declare any ensures c
 02783                }
 02784                if (fn.Body != null) {
 02785                  ExtremePredicateChecks(fn.Body, fn, CallingPosition.Positive);
 02786                }
 183852787              } else if (member is ExtremeLemma) {
 02788                var m = (ExtremeLemma)member;
 02789                m.Req.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02790                m.Ens.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02791                m.Decreases.Expressions.ForEach(e => ExtremeLemmaChecks(e, m));
 2792
 02793                if (m.Body != null) {
 02794                  ExtremeLemmaChecks(m.Body, m);
 02795                }
 183852796              } else if (member is ConstantField) {
 02797                var cf = (ConstantField)member;
 02798                if (cf.EnclosingModule.CallGraph.GetSCCSize(cf) != 1) {
 02799                  var r = cf.EnclosingModule.CallGraph.GetSCCRepresentative(cf);
 02800                  if (cycleErrorHasBeenReported.Contains(r)) {
 2801                    // An error has already been reported for this cycle, so don't report another.
 2802                    // Note, the representative, "r", may itself not be a const.
 02803                  } else {
 02804                    ReportCallGraphCycleError(cf, "const definition contains a cycle");
 02805                    cycleErrorHasBeenReported.Add(r);
 02806                  }
 02807                }
 02808              }
 183852809            }
 16602810          }
 2811
 33202812          if (d is RedirectingTypeDecl dd) {
 8302813            if (d.EnclosingModuleDefinition.CallGraph.GetSCCSize(dd) != 1) {
 02814              var r = d.EnclosingModuleDefinition.CallGraph.GetSCCRepresentative(dd);
 02815              if (cycleErrorHasBeenReported.Contains(r)) {
 2816                // An error has already been reported for this cycle, so don't report another.
 2817                // Note, the representative, "r", may itself not be a const.
 02818              } else if (dd is NewtypeDecl || dd is SubsetTypeDecl) {
 02819                ReportCallGraphCycleError(dd, $"recursive constraint dependency involving a {dd.WhatKind}");
 02820                cycleErrorHasBeenReported.Add(r);
 02821              }
 02822            }
 8302823          }
 24902824        }
 12452825      }
 2826
 2827      // ---------------------------------- Pass 3 ----------------------------------
 2828      // Further checks
 2829      // ----------------------------------------------------------------------------
 2830
 24902831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2832        // Check that type-parameter variance is respected in type definitions
 112052833        foreach (TopLevelDecl d in declarations) {
 41502834          if (d is IteratorDecl || d is ClassDecl) {
 62252835            foreach (var tp in d.TypeArgs) {
 4152836              if (tp.Variance != TypeParameter.TPVariance.Non) {
 02837                reporter.Error(MessageSource.Resolver, tp.tok, "{0} declarations only support non-variant type parameter
 02838              }
 4152839            }
 33202840          } else if (d is TypeSynonymDecl) {
 8302841            var dd = (TypeSynonymDecl)d;
 8302842            CheckVariance(dd.Rhs, dd, TypeParameter.TPVariance.Co, false);
 8302843          } else if (d is NewtypeDecl) {
 02844            var dd = (NewtypeDecl)d;
 02845            CheckVariance(dd.BaseType, dd, TypeParameter.TPVariance.Co, false);
 02846          } else if (d is DatatypeDecl) {
 02847            var dd = (DatatypeDecl)d;
 02848            foreach (var ctor in dd.Ctors) {
 02849              ctor.Formals.Iter(formal => CheckVariance(formal.Type, dd, TypeParameter.TPVariance.Co, false));
 02850            }
 02851          }
 24902852        }
 12452853      }
 2854
 24902855      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2856        // Check that usage of "this" is restricted before "new;" in constructor bodies,
 2857        // and that a class without any constructor only has fields with known initializers.
 2858        // Also check that static fields (which are necessarily const) have initializers.
 12452859        var cdci = new CheckDividedConstructorInit_Visitor(this);
 87152860        foreach (var cl in ModuleDefinition.AllTypesWithMembers(declarations)) {
 16602861          if (!(cl is ClassDecl)) {
 02862            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2863              // non-reference types (datatype, newtype, opaque) don't have constructors that can initialize fields
 02864              foreach (var member in cl.Members) {
 02865                if (member is ConstantField f && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02866                  CheckIsOkayWithoutRHS(f);
 02867                }
 02868              }
 02869            }
 02870            continue;
 2871          }
 20752872          if (cl is TraitDecl) {
 8302873            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2874              // traits never have constructors, but check for static consts
 12452875              foreach (var member in cl.Members) {
 02876                if (member is ConstantField f && f.IsStatic && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02877                  CheckIsOkayWithoutRHS(f);
 02878                }
 02879              }
 4152880            }
 4152881            continue;
 2882          }
 12452883          var hasConstructor = false;
 12452884          Field fieldWithoutKnownInitializer = null;
 588902885          foreach (var member in cl.Members) {
 183852886            if (member is Constructor) {
 02887              hasConstructor = true;
 02888              var constructor = (Constructor)member;
 02889              if (constructor.BodyInit != null) {
 02890                cdci.CheckInit(constructor.BodyInit);
 02891              }
 183852892            } else if (member is ConstantField && member.IsStatic) {
 02893              var f = (ConstantField)member;
 02894              if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract && f.Rhs == null && !f.IsExtern(Options, out _
 02895                CheckIsOkayWithoutRHS(f);
 02896              }
 188002897            } else if (member is Field && fieldWithoutKnownInitializer == null) {
 4152898              var f = (Field)member;
 4152899              if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2900                // fine
 4152901              } else if (!f.Type.KnownToHaveToAValue(f.IsGhost)) {
 02902                fieldWithoutKnownInitializer = f;
 02903              }
 4152904            }
 183852905          }
 24902906          if (!hasConstructor) {
 24902907            if (fieldWithoutKnownInitializer == null) {
 2908              // time to check inherited members
 37352909              foreach (var member in cl.InheritedMembers) {
 02910                if (member is Field) {
 02911                  var f = (Field)member;
 02912                  if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2913                    // fine
 02914                  } else if (!f.Type.Subst(cl.ParentFormalTypeParametersToActuals).KnownToHaveToAValue(f.IsGhost)) {
 02915                    fieldWithoutKnownInitializer = f;
 02916                    break;
 2917                  }
 02918                }
 02919              }
 12452920            }
 2921            // go through inherited members...
 12452922            if (fieldWithoutKnownInitializer != null) {
 02923              reporter.Error(MessageSource.Resolver, cl.tok, "class '{0}' with fields without known initializers, like '
 02924                cl.Name, fieldWithoutKnownInitializer.Name, fieldWithoutKnownInitializer.Type.Subst(cl.ParentFormalTypeP
 02925            }
 12452926          }
 12452927        }
 12452928      }
 2929      // Verifies that, in all compiled places, subset types in comprehensions have a compilable constraint
 12452930      new SubsetConstraintGhostChecker(this.Reporter).Traverse(declarations);
 12452931    }
 2932
 12452933    private void FillInPostConditionsAndBodiesOfPrefixLemmas(List<TopLevelDecl> declarations) {
 37352934      foreach (var com in ModuleDefinition.AllExtremeLemmas(declarations)) {
 02935        var prefixLemma = com.PrefixLemma;
 02936        if (prefixLemma == null) {
 02937          continue; // something went wrong during registration of the prefix lemma (probably a duplicated extreme lemma
 2938        }
 2939
 02940        var k = prefixLemma.Ins[0];
 02941        var focalPredicates = new HashSet<ExtremePredicate>();
 02942        if (com is GreatestLemma) {
 2943          // compute the postconditions of the prefix lemma
 02944          Contract.Assume(prefixLemma.Ens.Count == 0); // these are not supposed to have been filled in before
 02945          foreach (var p in com.Ens) {
 02946            var coConclusions = new HashSet<Expression>();
 02947            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, coConclusions, true, com);
 02948            var subst = new ExtremeLemmaSpecificationSubstituter(coConclusions, new IdentifierExpr(k.tok, k.Name),
 02949              this.reporter, true);
 02950            var post = subst.CloneExpr(p.E);
 02951            prefixLemma.Ens.Add(new AttributedExpression(post));
 02952            foreach (var e in coConclusions) {
 02953              var fce = e as FunctionCallExpr;
 02954              if (fce != null) {
 2955                // the other possibility is that "e" is a BinaryExpr
 02956                GreatestPredicate predicate = (GreatestPredicate)fce.Function;
 02957                focalPredicates.Add(predicate);
 2958                // For every focal predicate P in S, add to S all greatest predicates in the same strongly connected
 2959                // component (in the call graph) as P
 02960                foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(
 02961                           predicate)) {
 02962                  if (node is GreatestPredicate) {
 02963                    focalPredicates.Add((GreatestPredicate)node);
 02964                  }
 02965                }
 02966              }
 02967            }
 02968          }
 02969        } else {
 2970          // compute the preconditions of the prefix lemma
 02971          Contract.Assume(prefixLemma.Req.Count == 0); // these are not supposed to have been filled in before
 02972          foreach (var p in com.Req) {
 02973            var antecedents = new HashSet<Expression>();
 02974            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, antecedents, false, com);
 02975            var subst = new ExtremeLemmaSpecificationSubstituter(antecedents, new IdentifierExpr(k.tok, k.Name),
 02976              this.reporter, false);
 02977            var pre = subst.CloneExpr(p.E);
 02978            prefixLemma.Req.Add(new AttributedExpression(pre, p.Label, null));
 02979            foreach (var e in antecedents) {
 02980              var fce = (FunctionCallExpr)e; // we expect "antecedents" to contain only FunctionCallExpr's
 02981              LeastPredicate predicate = (LeastPredicate)fce.Function;
 02982              focalPredicates.Add(predicate);
 2983              // For every focal predicate P in S, add to S all least predicates in the same strongly connected
 2984              // component (in the call graph) as P
 02985              foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(predicate)) {
 02986                if (node is LeastPredicate) {
 02987                  focalPredicates.Add((LeastPredicate)node);
 02988                }
 02989              }
 02990            }
 02991          }
 02992        }
 2993
 02994        reporter.Info(MessageSource.Resolver, com.tok,
 02995          focalPredicates.Count == 0
 02996            ? $"{com.PrefixLemma.Name} has no focal predicates"
 02997            : $"{com.PrefixLemma.Name} with focal predicate{Util.Plural(focalPredicates.Count)} {Util.Comma(focalPredica
 2998        // Compute the statement body of the prefix lemma
 02999        Contract.Assume(prefixLemma.Body == null); // this is not supposed to have been filled in before
 03000        if (com.Body != null) {
 03001          var kMinusOne = new BinaryExpr(com.tok, BinaryExpr.Opcode.Sub, new IdentifierExpr(k.tok, k.Name),
 03002            new LiteralExpr(com.tok, 1));
 03003          var subst = new ExtremeLemmaBodyCloner(com, kMinusOne, focalPredicates, this.reporter);
 03004          var mainBody = subst.CloneBlockStmt(com.Body);
 3005          Expression kk;
 3006          Statement els;
 03007          if (k.Type.IsBigOrdinalType) {
 03008            kk = new MemberSelectExpr(k.tok, new IdentifierExpr(k.tok, k.Name), "Offset");
 3009            // As an "else" branch, we add recursive calls for the limit case.  When automatic induction is on,
 3010            // this get handled automatically, but we still want it in the case when automatic induction has been
 3011            // turned off.
 3012            //     forall k', params | k' < _k && Precondition {
 3013            //       pp(k', params);
 3014            //     }
 03015            Contract.Assume(builtIns.ORDINAL_Offset != null); // should have been filled in earlier
 03016            var kId = new IdentifierExpr(com.tok, k);
 03017            var kprimeVar = new BoundVar(com.tok, "_k'", Type.BigOrdinal);
 03018            var kprime = new IdentifierExpr(com.tok, kprimeVar);
 03019            var smaller = Expression.CreateLess(kprime, kId);
 3020
 03021            var bvs = new List<BoundVar>(); // the following loop populates bvs with k', params
 03022            var substMap = new Dictionary<IVariable, Expression>();
 03023            foreach (var inFormal in prefixLemma.Ins) {
 03024              if (inFormal == k) {
 03025                bvs.Add(kprimeVar);
 03026                substMap.Add(k, kprime);
 03027              } else {
 03028                var bv = new BoundVar(inFormal.tok, inFormal.Name, inFormal.Type);
 03029                bvs.Add(bv);
 03030                substMap.Add(inFormal, new IdentifierExpr(com.tok, bv));
 03031              }
 03032            }
 3033
 03034            Translator.RecursiveCallParameters(com.tok, prefixLemma, prefixLemma.TypeArgs, prefixLemma.Ins, null,
 03035              substMap, out var recursiveCallReceiver, out var recursiveCallArgs);
 03036            var methodSel = new MemberSelectExpr(com.tok, recursiveCallReceiver, prefixLemma.Name);
 03037            methodSel.Member = prefixLemma; // resolve here
 03038            methodSel.TypeApplication_AtEnclosingClass =
 03039              prefixLemma.EnclosingClass.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03040            methodSel.TypeApplication_JustMember =
 03041              prefixLemma.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03042            methodSel.Type = new InferredTypeProxy();
 03043            var recursiveCall = new CallStmt(com.RangeToken, new List<Expression>(), methodSel,
 03044              recursiveCallArgs.ConvertAll(e => new ActualBinding(null, e)));
 03045            recursiveCall.IsGhost = prefixLemma.IsGhost; // resolve here
 3046
 03047            var range = smaller; // The range will be strengthened later with the call's precondition, substituted
 3048            // appropriately (which can only be done once the precondition has been resolved).
 03049            var attrs = new Attributes("_autorequires", new List<Expression>(), null);
 3050#if VERIFY_CORRECTNESS_OF_TRANSLATION_FORALL_STATEMENT_RANGE
 3051              // don't add the :_trustWellformed attribute
 3052#else
 03053            attrs = new Attributes("_trustWellformed", new List<Expression>(), attrs);
 3054#endif
 03055            attrs = new Attributes("auto_generated", new List<Expression>(), attrs);
 03056            var forallBody = new BlockStmt(mainBody.RangeToken, new List<Statement>() { recursiveCall });
 03057            var forallStmt = new ForallStmt(mainBody.RangeToken, bvs, attrs, range,
 03058              new List<AttributedExpression>(), forallBody);
 03059            els = new BlockStmt(mainBody.RangeToken, new List<Statement>() { forallStmt });
 03060          } else {
 03061            kk = new IdentifierExpr(k.tok, k.Name);
 03062            els = null;
 03063          }
 3064
 03065          var kPositive = new BinaryExpr(com.tok, BinaryExpr.Opcode.Lt, new LiteralExpr(com.tok, 0), kk);
 03066          var condBody = new IfStmt(mainBody.RangeToken, false, kPositive, mainBody, els);
 03067          prefixLemma.Body = new BlockStmt(mainBody.RangeToken, new List<Statement>() { condBody });
 03068        }
 3069
 3070        // The prefix lemma now has all its components, so it's finally time we resolve it
 03071        currentClass = (TopLevelDeclWithMembers)prefixLemma.EnclosingClass;
 03072        allTypeParameters.PushMarker();
 03073        ResolveTypeParameters(currentClass.TypeArgs, false, currentClass);
 03074        ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03075        prefixLemma.Resolve(this);
 03076        allTypeParameters.PopMarker();
 03077        currentClass = null;
 03078        new CheckTypeInferenceVisitor(this).VisitMethod(prefixLemma);
 03079        CallGraphBuilder.VisitMethod(prefixLemma, reporter);
 03080        new BoundsDiscoveryVisitor(reporter).VisitMethod(prefixLemma);
 03081      }
 12453082    }
 3083
 03084    private void CheckIsOkayWithoutRHS(ConstantField f) {
 03085      if (f.IsGhost && !f.Type.IsNonempty) {
 03086        reporter.Error(MessageSource.Resolver, f.tok,
 03087          "{0}ghost const field '{1}' of type '{2}' (which may be empty) must give a defining value",
 03088          f.IsStatic ? "static " : "", f.Name, f.Type);
 03089      } else if (!f.IsGhost && !f.Type.HasCompilableValue) {
 03090        reporter.Error(MessageSource.Resolver, f.tok,
 03091          "{0}non-ghost const field '{1}' of type '{2}' (which does not have a default compiled value) must give a defin
 03092          f.IsStatic ? "static " : "", f.Name, f.Type);
 03093      }
 03094    }
 3095
 16603096    private void ResolveClassMembers_Pass1(TopLevelDeclWithMembers cl) {
 601353097      foreach (var member in cl.Members) {
 183853098        var prevErrCnt = reporter.Count(ErrorLevel.Error);
 367703099        if (prevErrCnt == reporter.Count(ErrorLevel.Error)) {
 234353100          if (member is Method method) {
 50503101            CheckForUnnecessaryEqualitySupportDeclarations(method, method.TypeArgs);
 50503102            CheckParameterDefaultValuesAreCompilable(method.Ins, method);
 101003103            if (method.Body != null) {
 50503104              ComputeGhostInterest(method.Body, method.IsGhost, method.IsLemmaLike ? "a " + method.WhatKind : null, meth
 50503105              CheckExpression(method.Body, this, method);
 50503106              new TailRecursion(reporter).DetermineTailRecursion(method);
 50503107            }
 3108
 313053109          } else if (member is Function function) {
 129203110            CheckForUnnecessaryEqualitySupportDeclarations(function, function.TypeArgs);
 129203111            CheckParameterDefaultValuesAreCompilable(function.Formals, function);
 258403112            if (function.ByMethodBody == null) {
 258403113              if (!function.IsGhost && function.Body != null) {
 129203114                ExpressionTester.CheckIsCompilable(Options, this, function.Body, function);
 129203115              }
 258403116              if (function.Body != null) {
 129203117                new TailRecursion(reporter).DetermineTailRecursion(function);
 129203118              }
 129203119            } else {
 03120              var m = function.ByMethodDecl;
 03121              if (m != null) {
 03122                Contract.Assert(!m.IsGhost);
 03123                ComputeGhostInterest(m.Body, false, null, m);
 03124                CheckExpression(m.Body, this, m);
 03125                new TailRecursion(reporter).DetermineTailRecursion(m);
 03126              } else {
 3127                // m should not be null, unless an error has been reported
 3128                // (e.g. function-by-method and method with the same name)
 03129                Contract.Assert(reporter.ErrorCount > 0);
 03130              }
 03131            }
 3132
 133353133          } else if (member is ConstantField field && field.Rhs != null && !field.IsGhost) {
 03134            ExpressionTester.CheckIsCompilable(Options, this, field.Rhs, field);
 03135          }
 3136
 363553137          if (prevErrCnt == reporter.Count(ErrorLevel.Error) && member is ICodeContext) {
 393303138            member.SubExpressions.Iter(e => CheckExpression(e, this, (ICodeContext)member));
 179703139          }
 183853140        }
 183853141      }
 16603142    }
 3143
 179703144    void CheckForUnnecessaryEqualitySupportDeclarations(MemberDecl member, List<TypeParameter> typeParameters) {
 179703145      if (member.IsGhost) {
 03146        foreach (var p in typeParameters.Where(p => p.SupportsEquality)) {
 03147          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, p.tok,
 03148            $"type parameter {p.Name} of ghost {member.WhatKind} {member.Name} is declared (==), which is unnecessary be
 03149        }
 03150      }
 179703151    }
 3152
 3153    /// <summary>
 3154    /// Check that default-value expressions are compilable, for non-ghost formals.
 3155    /// </summary>
 179703156    void CheckParameterDefaultValuesAreCompilable(List<Formal> formals, ICodeContext codeContext) {
 3157      Contract.Requires(formals != null);
 3158
 983903159      foreach (var formal in formals.Where(f => f.DefaultValue != null)) {
 03160        if ((!codeContext.IsGhost || codeContext is DatatypeDecl) && !formal.IsGhost) {
 03161          ExpressionTester.CheckIsCompilable(Options, this, formal.DefaultValue, codeContext);
 03162        }
 03163        CheckExpression(formal.DefaultValue, this, codeContext);
 03164      }
 179703165    }
 3166
 03167    void ReportCallGraphCycleError(ICallable start, string msg) {
 3168      Contract.Requires(start != null);
 3169      Contract.Requires(msg != null);
 03170      var scc = start.EnclosingModule.CallGraph.GetSCC(start);
 03171      scc.Reverse();
 03172      var startIndex = scc.IndexOf(start);
 03173      Contract.Assert(0 <= startIndex);
 03174      scc = Util.Concat(scc.GetRange(startIndex, scc.Count - startIndex), scc.GetRange(0, startIndex));
 03175      ReportCycleError(scc, c => c.Tok, c => c.NameRelativeToModule, msg);
 03176    }
 3177
 03178    void ReportCycleError<X>(List<X> cycle, Func<X, IToken> toTok, Func<X, string> toString, string msg) {
 3179      Contract.Requires(cycle != null);
 3180      Contract.Requires(cycle.Count != 0);
 3181      Contract.Requires(toTok != null);
 3182      Contract.Requires(toString != null);
 3183      Contract.Requires(msg != null);
 3184
 03185      var start = cycle[0];
 03186      var cy = Util.Comma(" -> ", cycle, toString);
 03187      reporter.Error(MessageSource.Resolver, toTok(start), $"{msg}: {cy} -> {toString(start)}");
 03188    }
 3189
 3190    /// <summary>
 3191    /// Returns the largest value that can be stored in bitvector type "t".
 3192    /// </summary>
 03193    public static BigInteger MaxBV(Type t) {
 3194      Contract.Requires(t != null);
 3195      Contract.Requires(t.IsBitVectorType);
 03196      return MaxBV(t.AsBitVectorType.Width);
 03197    }
 3198
 3199    /// <summary>
 3200    /// Returns the largest value that can be stored in bitvector type of "bits" width.
 3201    /// </summary>
 03202    public static BigInteger MaxBV(int bits) {
 3203      Contract.Requires(0 <= bits);
 03204      return BigInteger.Pow(new BigInteger(2), bits) - BigInteger.One;
 03205    }
 3206
 03207    private void FigureOutNativeType(NewtypeDecl dd) {
 3208      Contract.Requires(dd != null);
 3209
 3210      // Look at the :nativeType attribute, if any
 3211      bool mustUseNativeType;
 03212      List<NativeType> nativeTypeChoices = null;  // null means "no preference"
 03213      var args = Attributes.FindExpressions(dd.Attributes, "nativeType");
 03214      if (args != null && !dd.BaseType.IsNumericBased(Type.NumericPersuasion.Int)) {
 03215        reporter.Error(MessageSource.Resolver, dd, ":nativeType can only be used on integral types");
 03216        return;
 03217      } else if (args == null) {
 3218        // There was no :nativeType attribute
 03219        mustUseNativeType = false;
 03220      } else if (args.Count == 0) {
 03221        mustUseNativeType = true;
 03222      } else {
 03223        var arg0Lit = args[0] as LiteralExpr;
 03224        if (arg0Lit != null && arg0Lit.Value is bool) {
 03225          if (!(bool)arg0Lit.Value) {
 3226            // {:nativeType false} says "don't use native type", so our work here is done
 03227            return;
 3228          }
 03229          mustUseNativeType = true;
 03230        } else {
 03231          mustUseNativeType = true;
 03232          nativeTypeChoices = new List<NativeType>();
 03233          foreach (var arg in args) {
 03234            if (arg is LiteralExpr lit && lit.Value is string s) {
 3235              // Get the NativeType for "s"
 03236              foreach (var nativeT in NativeTypes) {
 03237                if (nativeT.Name == s) {
 03238                  nativeTypeChoices.Add(nativeT);
 03239                  goto FoundNativeType;
 3240                }
 03241              }
 03242              reporter.Error(MessageSource.Resolver, dd, ":nativeType '{0}' not known", s);
 03243              return;
 03244            FoundNativeType:;
 03245            } else {
 03246              reporter.Error(MessageSource.Resolver, arg, "unexpected :nativeType argument");
 03247              return;
 3248            }
 03249          }
 03250        }
 03251      }
 3252
 3253      // Figure out the variable and constraint.  Usually, these would be just .Var and .Constraint, but
 3254      // in the case .Var is null, these can be computed from the .BaseType recursively.
 03255      var ddVar = dd.Var;
 03256      var ddConstraint = dd.Constraint;
 03257      for (var ddWhereConstraintsAre = dd; ddVar == null;) {
 03258        ddWhereConstraintsAre = ddWhereConstraintsAre.BaseType.AsNewtype;
 03259        if (ddWhereConstraintsAre == null) {
 03260          break;
 3261        }
 03262        ddVar = ddWhereConstraintsAre.Var;
 03263        ddConstraint = ddWhereConstraintsAre.Constraint;
 03264      }
 3265      List<ComprehensionExpr.BoundedPool> bounds;
 03266      if (ddVar == null) {
 3267        // There are no bounds at all
 03268        bounds = new List<ComprehensionExpr.BoundedPool>();
 03269      } else {
 03270        bounds = DiscoverAllBounds_SingleVar(ddVar, ddConstraint);
 03271      }
 3272
 3273      // Returns null if the argument is a constrained newtype (recursively)
 3274      // Returns the transitive base type if the argument is recusively unconstrained
 03275      Type AsUnconstrainedType(Type t) {
 03276        while (true) {
 03277          if (t.AsNewtype == null) {
 03278            return t;
 3279          }
 3280
 03281          if (t.AsNewtype.Constraint != null) {
 03282            return null;
 3283          }
 3284
 03285          t = t.AsNewtype.BaseType;
 03286        }
 03287      }
 3288
 3289      // Find which among the allowable native types can hold "dd". Give an
 3290      // error for any user-specified native type that's not big enough.
 03291      var bigEnoughNativeTypes = new List<NativeType>();
 3292      // But first, define a local, recursive function GetConst/GetAnyConst:
 3293      // These fold any constant computations, including symbolic constants,
 3294      // returning null if folding is not possible. If an operation is undefined
 3295      // (divide by zero, conversion out of range, etc.), then null is returned.
 03296      Func<Expression, BigInteger?> GetConst = null;
 03297      Func<Expression, Stack<ConstantField>, Object> GetAnyConst = null;
 03298      GetAnyConst = (Expression e, Stack<ConstantField> consts) => {
 03299        if (e is LiteralExpr l) {
 03300          return l.Value;
 03301        } else if (e is UnaryOpExpr un) {
 03302          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot && GetAnyConst(un.E, consts) is bool b) {
 03303            return !b;
 03304          }
 03305          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BVNot && GetAnyConst(un.E, consts) is BigInteger i) {
 03306            return ((BigInteger.One << un.Type.AsBitVectorType.Width) - 1) ^ i;
 03307          }
 03308          // TODO: This only handles strings; generalize to other collections?
 03309          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.SeqLength && GetAnyConst(un.E, consts) is string ss) {
 03310            return (BigInteger)(ss.Length);
 03311          }
 03312        } else if (e is MemberSelectExpr m) {
 03313          if (m.Member is ConstantField c && c.IsStatic && c.Rhs != null) {
 03314            // This aspect of type resolution happens before the check for cyclic references
 03315            // so we have to do a check here as well. If cyclic, null is silently returned,
 03316            // counting on the later error message to alert the user.
 03317            if (consts.Contains(c)) { return null; }
 03318            consts.Push(c);
 03319            Object o = GetAnyConst(c.Rhs, consts);
 03320            consts.Pop();
 03321            return o;
 03322          } else if (m.Member is SpecialField sf) {
 03323            string nm = sf.Name;
 03324            if (nm == "Floor") {
 03325              Object ee = GetAnyConst(m.Obj, consts);
 03326              if (ee != null && m.Obj.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03327                ((BaseTypes.BigDec)ee).FloorCeiling(out var f, out _);
 03328                return f;
 03329              }
 03330            }
 03331          }
 03332        } else if (e is BinaryExpr bin) {
 03333          Object e0 = GetAnyConst(bin.E0, consts);
 03334          Object e1 = GetAnyConst(bin.E1, consts);
 03335          bool isBool = bin.E0.Type == Type.Bool && bin.E1.Type == Type.Bool;
 03336          bool shortCircuit = isBool && (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.And
 03337                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Or
 03338                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Imp);
 03339
 03340          if (e0 == null || (!shortCircuit && e1 == null)) { return null; }
 03341          bool isAnyReal = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)
 03342                        && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Real);
 03343          bool isAnyInt = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Int)
 03344                       && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Int);
 03345          bool isReal = bin.Type.IsRealType;
 03346          bool isInt = bin.Type.IsIntegerType;
 03347          bool isBV = bin.E0.Type.IsBitVectorType;
 03348          int width = isBV ? bin.E0.Type.AsBitVectorType.Width : 0;
 03349          bool isString = e0 is string && e1 is string;
 03350          switch (bin.ResolvedOp) {
 03351            case BinaryExpr.ResolvedOpcode.Add:
 03352              if (isInt) {
 03353                return (BigInteger)e0 + (BigInteger)e1;
 03354              }
 03355
 03356              if (isBV) {
 03357                return ((BigInteger)e0 + (BigInteger)e1) & MaxBV(bin.Type);
 03358              }
 03359
 03360              if (isReal) {
 03361                return (BaseTypes.BigDec)e0 + (BaseTypes.BigDec)e1;
 03362              }
 03363
 03364              break;
 03365            case BinaryExpr.ResolvedOpcode.Concat:
 03366              if (isString) {
 03367                return (string)e0 + (string)e1;
 03368              }
 03369
 03370              break;
 03371            case BinaryExpr.ResolvedOpcode.Sub:
 03372              if (isInt) {
 03373                return (BigInteger)e0 - (BigInteger)e1;
 03374              }
 03375
 03376              if (isBV) {
 03377                return ((BigInteger)e0 - (BigInteger)e1) & MaxBV(bin.Type);
 03378              }
 03379
 03380              if (isReal) {
 03381                return (BaseTypes.BigDec)e0 - (BaseTypes.BigDec)e1;
 03382              }
 03383              // Allow a special case: If the result type is a newtype that is integer-based (i.e., isInt && !isInteger)
 03384              // then we generally do not fold the operations, because we do not determine whether the
 03385              // result of the operation satisfies the new type constraint. However, on the occasion that
 03386              // a newtype aliases int without a constraint, it occurs that a value of the newtype is initialized
 03387              // with a negative value, which is represented as "0 - N", that is, it comes to this case. It
 03388              // is a nuisance not to constant-fold the result, as not doing so can alter the determination
 03389              // of the representation type.
 03390              if (isAnyInt && AsUnconstrainedType(bin.Type) != null) {
 03391                return ((BigInteger)e0) - ((BigInteger)e1);
 03392              }
 03393              break;
 03394            case BinaryExpr.ResolvedOpcode.Mul:
 03395              if (isInt) {
 03396                return (BigInteger)e0 * (BigInteger)e1;
 03397              }
 03398
 03399              if (isBV) {
 03400                return ((BigInteger)e0 * (BigInteger)e1) & MaxBV(bin.Type);
 03401              }
 03402
 03403              if (isReal) {
 03404                return (BaseTypes.BigDec)e0 * (BaseTypes.BigDec)e1;
 03405              }
 03406
 03407              break;
 03408            case BinaryExpr.ResolvedOpcode.BitwiseAnd:
 03409              Contract.Assert(isBV);
 03410              return (BigInteger)e0 & (BigInteger)e1;
 03411            case BinaryExpr.ResolvedOpcode.BitwiseOr:
 03412              Contract.Assert(isBV);
 03413              return (BigInteger)e0 | (BigInteger)e1;
 03414            case BinaryExpr.ResolvedOpcode.BitwiseXor:
 03415              Contract.Assert(isBV);
 03416              return (BigInteger)e0 ^ (BigInteger)e1;
 03417            case BinaryExpr.ResolvedOpcode.Div:
 03418              if (isInt) {
 03419                if ((BigInteger)e1 == 0) {
 03420                  return null; // Divide by zero
 03421                } else {
 03422                  BigInteger a0 = (BigInteger)e0;
 03423                  BigInteger a1 = (BigInteger)e1;
 03424                  BigInteger d = a0 / a1;
 03425                  return a0 >= 0 || a0 == d * a1 ? d : a1 > 0 ? d - 1 : d + 1;
 03426                }
 03427              }
 03428              if (isBV) {
 03429                if ((BigInteger)e1 == 0) {
 03430                  return null; // Divide by zero
 03431                } else {
 03432                  return ((BigInteger)e0) / ((BigInteger)e1);
 03433                }
 03434              }
 03435              if (isReal) {
 03436                if ((BaseTypes.BigDec)e1 == BaseTypes.BigDec.ZERO) {
 03437                  return null; // Divide by zero
 03438                } else {
 03439                  // BigDec does not have divide and is not a representation of rationals, so we don't do constant foldi
 03440                  return null;
 03441                }
 03442              }
 03443
 03444              break;
 03445            case BinaryExpr.ResolvedOpcode.Mod:
 03446              if (isInt) {
 03447                if ((BigInteger)e1 == 0) {
 03448                  return null; // Mod by zero
 03449                } else {
 03450                  BigInteger a = BigInteger.Abs((BigInteger)e1);
 03451                  BigInteger d = (BigInteger)e0 % a;
 03452                  return (BigInteger)e0 >= 0 ? d : d + a;
 03453                }
 03454              }
 03455              if (isBV) {
 03456                if ((BigInteger)e1 == 0) {
 03457                  return null; // Mod by zero
 03458                } else {
 03459                  return (BigInteger)e0 % (BigInteger)e1;
 03460                }
 03461              }
 03462              break;
 03463            case BinaryExpr.ResolvedOpcode.LeftShift: {
 03464                if ((BigInteger)e1 < 0) {
 03465                  return null; // Negative shift
 03466                }
 03467                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03468                  return null; // Shift is too large
 03469                }
 03470                return ((BigInteger)e0 << (int)(BigInteger)e1) & MaxBV(bin.E0.Type);
 03471              }
 03472            case BinaryExpr.ResolvedOpcode.RightShift: {
 03473                if ((BigInteger)e1 < 0) {
 03474                  return null; // Negative shift
 03475                }
 03476                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03477                  return null; // Shift too large
 03478                }
 03479                return (BigInteger)e0 >> (int)(BigInteger)e1;
 03480              }
 03481            case BinaryExpr.ResolvedOpcode.And: {
 03482                if ((bool)e0 && e1 == null) {
 03483                  return null;
 03484                }
 03485
 03486                return (bool)e0 && (bool)e1;
 03487              }
 03488            case BinaryExpr.ResolvedOpcode.Or: {
 03489                if (!(bool)e0 && e1 == null) {
 03490                  return null;
 03491                }
 03492
 03493                return (bool)e0 || (bool)e1;
 03494              }
 03495            case BinaryExpr.ResolvedOpcode.Imp: { // ==> and <==
 03496                if ((bool)e0 && e1 == null) {
 03497                  return null;
 03498                }
 03499
 03500                return !(bool)e0 || (bool)e1;
 03501              }
 03502            case BinaryExpr.ResolvedOpcode.Iff: return (bool)e0 == (bool)e1; // <==>
 03503            case BinaryExpr.ResolvedOpcode.Gt:
 03504              if (isAnyInt) {
 03505                return (BigInteger)e0 > (BigInteger)e1;
 03506              }
 03507
 03508              if (isBV) {
 03509                return (BigInteger)e0 > (BigInteger)e1;
 03510              }
 03511
 03512              if (isAnyReal) {
 03513                return (BaseTypes.BigDec)e0 > (BaseTypes.BigDec)e1;
 03514              }
 03515
 03516              break;
 03517            case BinaryExpr.ResolvedOpcode.GtChar:
 03518              if (bin.E0.Type.IsCharType) {
 03519                return ((string)e0)[0] > ((string)e1)[0];
 03520              }
 03521
 03522              break;
 03523            case BinaryExpr.ResolvedOpcode.Ge:
 03524              if (isAnyInt) {
 03525                return (BigInteger)e0 >= (BigInteger)e1;
 03526              }
 03527
 03528              if (isBV) {
 03529                return (BigInteger)e0 >= (BigInteger)e1;
 03530              }
 03531
 03532              if (isAnyReal) {
 03533                return (BaseTypes.BigDec)e0 >= (BaseTypes.BigDec)e1;
 03534              }
 03535
 03536              break;
 03537            case BinaryExpr.ResolvedOpcode.GeChar:
 03538              if (bin.E0.Type.IsCharType) {
 03539                return ((string)e0)[0] >= ((string)e1)[0];
 03540              }
 03541
 03542              break;
 03543            case BinaryExpr.ResolvedOpcode.Lt:
 03544              if (isAnyInt) {
 03545                return (BigInteger)e0 < (BigInteger)e1;
 03546              }
 03547
 03548              if (isBV) {
 03549                return (BigInteger)e0 < (BigInteger)e1;
 03550              }
 03551
 03552              if (isAnyReal) {
 03553                return (BaseTypes.BigDec)e0 < (BaseTypes.BigDec)e1;
 03554              }
 03555
 03556              break;
 03557            case BinaryExpr.ResolvedOpcode.LtChar:
 03558              if (bin.E0.Type.IsCharType) {
 03559                return ((string)e0)[0] < ((string)e1)[0];
 03560              }
 03561
 03562              break;
 03563            case BinaryExpr.ResolvedOpcode.ProperPrefix:
 03564              if (isString) {
 03565                return ((string)e1).StartsWith((string)e0) && !((string)e1).Equals((string)e0);
 03566              }
 03567
 03568              break;
 03569            case BinaryExpr.ResolvedOpcode.Le:
 03570              if (isAnyInt) {
 03571                return (BigInteger)e0 <= (BigInteger)e1;
 03572              }
 03573
 03574              if (isBV) {
 03575                return (BigInteger)e0 <= (BigInteger)e1;
 03576              }
 03577
 03578              if (isAnyReal) {
 03579                return (BaseTypes.BigDec)e0 <= (BaseTypes.BigDec)e1;
 03580              }
 03581
 03582              break;
 03583            case BinaryExpr.ResolvedOpcode.LeChar:
 03584              if (bin.E0.Type.IsCharType) {
 03585                return ((string)e0)[0] <= ((string)e1)[0];
 03586              }
 03587
 03588              break;
 03589            case BinaryExpr.ResolvedOpcode.Prefix:
 03590              if (isString) {
 03591                return ((string)e1).StartsWith((string)e0);
 03592              }
 03593
 03594              break;
 03595            case BinaryExpr.ResolvedOpcode.EqCommon: {
 03596                if (isBool) {
 03597                  return (bool)e0 == (bool)e1;
 03598                } else if (isAnyInt || isBV) {
 03599                  return (BigInteger)e0 == (BigInteger)e1;
 03600                } else if (isAnyReal) {
 03601                  return (BaseTypes.BigDec)e0 == (BaseTypes.BigDec)e1;
 03602                } else if (bin.E0.Type.IsCharType) {
 03603                  return ((string)e0)[0] == ((string)e1)[0];
 03604                }
 03605                break;
 03606              }
 03607            case BinaryExpr.ResolvedOpcode.SeqEq:
 03608              if (isString) {
 03609                return (string)e0 == (string)e1;
 03610              }
 03611              break;
 03612            case BinaryExpr.ResolvedOpcode.SeqNeq:
 03613              if (isString) {
 03614                return (string)e0 != (string)e1;
 03615              }
 03616              break;
 03617            case BinaryExpr.ResolvedOpcode.NeqCommon: {
 03618                if (isBool) {
 03619                  return (bool)e0 != (bool)e1;
 03620                } else if (isAnyInt || isBV) {
 03621                  return (BigInteger)e0 != (BigInteger)e1;
 03622                } else if (isAnyReal) {
 03623                  return (BaseTypes.BigDec)e0 != (BaseTypes.BigDec)e1;
 03624                } else if (bin.E0.Type.IsCharType) {
 03625                  return ((string)e0)[0] != ((string)e1)[0];
 03626                } else if (isString) {
 03627                  return (string)e0 != (string)e1;
 03628                }
 03629                break;
 03630              }
 03631          }
 03632        } else if (e is ConversionExpr ce) {
 03633          object o = GetAnyConst(ce.E, consts);
 03634          if (o == null || ce.E.Type == ce.Type) {
 03635            return o;
 03636          }
 03637
 03638          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03639                ce.Type.IsBitVectorType) {
 03640            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03641            if (ff < 0 || ff > MaxBV(ce.Type)) {
 03642              return null; // Out of range
 03643            }
 03644            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03645              return null; // Out of range
 03646            }
 03647            return ff;
 03648          }
 03649
 03650          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03651                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03652            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03653            if (AsUnconstrainedType(ce.Type) == null) {
 03654              return null;
 03655            }
 03656
 03657            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03658              return null; // Argument not an integer
 03659            }
 03660            return ff;
 03661          }
 03662
 03663          if (ce.E.Type.IsBitVectorType &&
 03664                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03665            if (AsUnconstrainedType(ce.Type) == null) {
 03666              return null;
 03667            }
 03668
 03669            return o;
 03670          }
 03671
 03672          if (ce.E.Type.IsBitVectorType &&
 03673                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03674            if (AsUnconstrainedType(ce.Type) == null) {
 03675              return null;
 03676            }
 03677
 03678            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03679          }
 03680
 03681          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03682                ce.Type.IsBitVectorType) {
 03683            BigInteger b = (BigInteger)o;
 03684            if (b < 0 || b > MaxBV(ce.Type)) {
 03685              return null; // Argument out of range
 03686            }
 03687            return o;
 03688          }
 03689
 03690          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03691                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03692            // This case includes int-based newtypes to int-based new types
 03693            if (AsUnconstrainedType(ce.Type) == null) {
 03694              return null;
 03695            }
 03696
 03697            return o;
 03698          }
 03699
 03700          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03701                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03702            // This case includes real-based newtypes to real-based new types
 03703            if (AsUnconstrainedType(ce.Type) == null) {
 03704              return null;
 03705            }
 03706
 03707            return o;
 03708          }
 03709
 03710          if (ce.E.Type.IsBitVectorType && ce.Type.IsBitVectorType) {
 03711            BigInteger b = (BigInteger)o;
 03712            if (b < 0 || b > MaxBV(ce.Type)) {
 03713              return null; // Argument out of range
 03714            }
 03715            return o;
 03716          }
 03717
 03718          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03719                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03720            if (AsUnconstrainedType(ce.Type) == null) {
 03721              return null;
 03722            }
 03723
 03724            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03725          }
 03726
 03727          if (ce.E.Type.IsCharType && ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03728            char c = ((String)o)[0];
 03729            if (AsUnconstrainedType(ce.Type) == null) {
 03730              return null;
 03731            }
 03732
 03733            return new BigInteger(((string)o)[0]);
 03734          }
 03735
 03736          if (ce.E.Type.IsCharType && ce.Type.IsBitVectorType) {
 03737            char c = ((String)o)[0];
 03738            if ((int)c > MaxBV(ce.Type)) {
 03739              return null; // Argument out of range
 03740            }
 03741            return new BigInteger(((string)o)[0]);
 03742          }
 03743
 03744          if ((ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || ce.E.Type.IsBitVectorType) &&
 03745                ce.Type.IsCharType) {
 03746            BigInteger b = (BigInteger)o;
 03747            if (b < BigInteger.Zero || b > new BigInteger(65535)) {
 03748              return null; // Argument out of range
 03749            }
 03750            return ((char)(int)b).ToString();
 03751          }
 03752
 03753          if (ce.E.Type.IsCharType &&
 03754              ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03755            if (AsUnconstrainedType(ce.Type) == null) {
 03756              return null;
 03757            }
 03758
 03759            return BaseTypes.BigDec.FromInt(((string)o)[0]);
 03760          }
 03761
 03762          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03763                ce.Type.IsCharType) {
 03764            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03765            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03766              return null; // Argument not an integer
 03767            }
 03768            if (ff < BigInteger.Zero || ff > new BigInteger(65535)) {
 03769              return null; // Argument out of range
 03770            }
 03771            return ((char)(int)ff).ToString();
 03772          }
 03773
 03774        } else if (e is SeqSelectExpr sse) {
 03775          var b = GetAnyConst(sse.Seq, consts) as string;
 03776          BigInteger index = (BigInteger)GetAnyConst(sse.E0, consts);
 03777          if (b == null) {
 03778            return null;
 03779          }
 03780
 03781          if (index < 0 || index >= b.Length || index > Int32.MaxValue) {
 03782            return null; // Index out of range
 03783          }
 03784          return b[(int)index].ToString();
 03785        } else if (e is ITEExpr ite) {
 03786          Object b = GetAnyConst(ite.Test, consts);
 03787          if (b == null) {
 03788            return null;
 03789          }
 03790
 03791          return ((bool)b) ? GetAnyConst(ite.Thn, consts) : GetAnyConst(ite.Els, consts);
 03792        } else if (e is ConcreteSyntaxExpression n) {
 03793          return GetAnyConst(n.ResolvedExpression, consts);
 03794        } else {
 03795          return null;
 03796        }
 03797        return null;
 03798      };
 03799      GetConst = (Expression e) => {
 03800        Object ee = GetAnyConst(e.Resolved ?? e, new Stack<ConstantField>());
 03801        return ee as BigInteger?;
 03802      };
 3803      // Now, then, let's go through them types.
 3804      // FIXME - should first go through the bounds to find the most constraining values
 3805      // then check those values against the possible types. Note that also presumes the types are in order.
 03806      BigInteger? lowest = null;
 03807      BigInteger? highest = null;
 03808      foreach (var bound in bounds) {
 03809        if (bound is ComprehensionExpr.IntBoundedPool) {
 03810          var bnd = (ComprehensionExpr.IntBoundedPool)bound;
 03811          if (bnd.LowerBound != null) {
 03812            BigInteger? lower = GetConst(bnd.LowerBound);
 03813            if (lower != null && (lowest == null || lower < lowest)) {
 03814              lowest = lower;
 03815            }
 03816          }
 03817          if (bnd.UpperBound != null) {
 03818            BigInteger? upper = GetConst(bnd.UpperBound);
 03819            if (upper != null && (highest == null || upper > highest)) {
 03820              highest = upper;
 03821            }
 03822          }
 03823        }
 03824      }
 03825      foreach (var nativeT in nativeTypeChoices ?? NativeTypes) {
 03826        bool lowerOk = (lowest != null && nativeT.LowerBound <= lowest);
 03827        bool upperOk = (highest != null && nativeT.UpperBound >= highest);
 03828        if (lowerOk && upperOk) {
 03829          bigEnoughNativeTypes.Add(nativeT);
 03830        } else if (nativeTypeChoices != null) {
 03831          reporter.Error(MessageSource.Resolver, dd,
 03832            "Dafny's heuristics failed to confirm '{0}' to be a compatible native type.  " +
 03833            "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additio
 03834            nativeT.Name);
 03835          return;
 3836        }
 03837      }
 3838
 3839      // Finally, of the big-enough native types, pick the first one that is
 3840      // supported by the selected target compiler.
 03841      foreach (var nativeT in bigEnoughNativeTypes) {
 03842        if (Options.Backend.SupportedNativeTypes.Contains(nativeT.Name)) {
 03843          dd.NativeType = nativeT;
 03844          break;
 3845        }
 03846      }
 03847      if (dd.NativeType != null) {
 3848        // Give an info message saying which type was selected--unless the user requested
 3849        // one particular native type, in which case that must have been the one picked.
 03850        if (nativeTypeChoices != null && nativeTypeChoices.Count == 1) {
 03851          Contract.Assert(dd.NativeType == nativeTypeChoices[0]);
 03852        } else {
 03853          reporter.Info(MessageSource.Resolver, dd.tok, "newtype " + dd.Name + " resolves as {:nativeType \"" + dd.Nativ
 03854        }
 03855      } else if (nativeTypeChoices != null) {
 03856        reporter.Error(MessageSource.Resolver, dd,
 03857          "None of the types given in :nativeType arguments is supported by the current compilation target. Try supplyin
 03858      } else if (mustUseNativeType) {
 03859        reporter.Error(MessageSource.Resolver, dd,
 03860          "Dafny's heuristics cannot find a compatible native type.  " +
 03861          "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additiona
 03862      }
 03863    }
 3864
 3865    /// <summary>
 3866    /// Check that the 'older' modifier on parameters is used correctly and report any errors of the contrary.
 3867    /// </summary>
 129203868    void CheckOlderParameters(Function f) {
 3869      Contract.Requires(f != null);
 3870
 256603871      if (!f.ResultType.IsBoolType || f is PrefixPredicate || f is ExtremePredicate) {
 3872        // parameters are not allowed to be marked 'older'
 1374903873        foreach (var formal in f.Formals) {
 330903874          if (formal.IsOlder) {
 03875            reporter.Error(MessageSource.Resolver, formal.tok, "only predicates and two-state predicates are allowed 'ol
 03876          }
 330903877        }
 127403878      }
 129203879    }
 3880
 3881    // ------------------------------------------------------------------------------------------------------
 3882    // ----- CheckExpression --------------------------------------------------------------------------------
 3883    // ------------------------------------------------------------------------------------------------------
 3884    #region CheckExpression
 3885    /// <summary>
 3886    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3887    /// checks for hint restrictions in any CalcStmt.
 3888    /// </summary>
 221903889    void CheckExpression(Expression expr, Resolver resolver, ICodeContext codeContext) {
 3890      Contract.Requires(expr != null);
 3891      Contract.Requires(resolver != null);
 3892      Contract.Requires(codeContext != null);
 221903893      var v = new CheckExpression_Visitor(resolver, codeContext);
 221903894      v.Visit(expr);
 221903895    }
 3896    /// <summary>
 3897    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3898    /// checks for hint restrictions in any CalcStmt. In any ghost context, it also
 3899    /// changes the bound variables of all let- and let-such-that expressions to ghost.
 3900    /// It also performs substitutions in DefaultValueExpression's.
 3901    /// </summary>
 50503902    void CheckExpression(Statement stmt, Resolver resolver, ICodeContext codeContext) {
 3903      Contract.Requires(stmt != null);
 3904      Contract.Requires(resolver != null);
 3905      Contract.Requires(codeContext != null);
 50503906      var v = new CheckExpression_Visitor(resolver, codeContext);
 50503907      v.Visit(stmt);
 50503908    }
 3909    class CheckExpression_Visitor : ResolverBottomUpVisitor {
 3910      readonly ICodeContext CodeContext;
 3911      public CheckExpression_Visitor(Resolver resolver, ICodeContext codeContext)
 544803912        : base(resolver) {
 3913        Contract.Requires(resolver != null);
 3914        Contract.Requires(codeContext != null);
 272403915        CodeContext = codeContext;
 272403916      }
 27706853917      protected override void VisitOneExpr(Expression expr) {
 27706853918        if (expr is StmtExpr) {
 03919          var e = (StmtExpr)expr;
 03920          resolver.ComputeGhostInterest(e.S, true, "a statement expression", CodeContext);
 28091853921        } else if (expr is LetExpr) {
 385003922          var e = (LetExpr)expr;
 385003923          if (CodeContext.IsGhost) {
 03924            foreach (var bv in e.BoundVars) {
 03925              bv.MakeGhost();
 03926            }
 03927          }
 385003928        }
 27706853929      }
 3930
 11988003931      protected override void VisitOneStmt(Statement stmt) {
 11988003932        if (stmt is CalcStmt calc) {
 03933          foreach (var h in calc.Hints) {
 03934            resolver.CheckLocalityUpdates(h, new HashSet<LocalVariable>(), "a hint");
 03935          }
 11988003936        } else if (stmt is AssertStmt astmt && astmt.Proof != null) {
 03937          resolver.CheckLocalityUpdates(astmt.Proof, new HashSet<LocalVariable>(), "an assert-by body");
 11988003938        } else if (stmt is ForallStmt forall && forall.Body != null) {
 03939          resolver.CheckLocalityUpdates(forall.Body, new HashSet<LocalVariable>(), "a forall statement");
 03940        }
 11988003941      }
 3942    }
 3943    #endregion
 3944
 3945    // ------------------------------------------------------------------------------------------------------
 3946    // ----- FuelAdjustmentChecks ---------------------------------------------------------------------------
 3947    // ------------------------------------------------------------------------------------------------------
 3948    #region FuelAdjustmentChecks
 3949
 6088003950    protected void CheckForFuelAdjustments(IToken tok, Attributes attrs, ModuleDefinition currentModule) {
 6088003951      List<List<Expression>> results = Attributes.FindAllExpressions(attrs, "fuel");
 3952
 6088003953      if (results != null) {
 03954        foreach (List<Expression> args in results) {
 03955          if (args != null && args.Count >= 2) {
 3956            // Try to extract the function from the first argument
 03957            MemberSelectExpr selectExpr = args[0].Resolved as MemberSelectExpr;
 03958            if (selectExpr != null) {
 03959              Function f = selectExpr.Member as Function;
 03960              if (f != null) {
 03961                f.IsFueled = true;
 03962                if (args.Count >= 3) {
 03963                  LiteralExpr literalLow = args[1] as LiteralExpr;
 03964                  LiteralExpr literalHigh = args[2] as LiteralExpr;
 03965                  if (literalLow != null && literalLow.Value is BigInteger && literalHigh != null && literalHigh.Value i
 03966                    BigInteger low = (BigInteger)literalLow.Value;
 03967                    BigInteger high = (BigInteger)literalHigh.Value;
 03968                    if (!(high == low + 1 || (low == 0 && high == 0))) {
 03969                      reporter.Error(MessageSource.Resolver, tok, "fuel setting for function {0} must have high value ==
 03970                    }
 03971                  }
 03972                }
 03973              }
 03974            }
 03975          }
 03976        }
 03977      }
 6088003978    }
 3979
 3980    public class FuelAdjustment_Context {
 3981      public ModuleDefinition currentModule;
 179703982      public FuelAdjustment_Context(ModuleDefinition currentModule) {
 89853983        this.currentModule = currentModule;
 89853984      }
 3985    }
 3986
 3987    class FuelAdjustment_Visitor : ResolverTopDownVisitor<FuelAdjustment_Context> {
 3988      public FuelAdjustment_Visitor(Resolver resolver)
 179703989        : base(resolver) {
 3990        Contract.Requires(resolver != null);
 89853991      }
 3992
 5994003993      protected override bool VisitOneStmt(Statement stmt, ref FuelAdjustment_Context st) {
 5994003994        resolver.CheckForFuelAdjustments(stmt.Tok, stmt.Attributes, st.currentModule);
 5994003995        return true;
 5994003996      }
 3997    }
 3998
 3999    #endregion FuelAdjustmentChecks
 4000
 4001    // ------------------------------------------------------------------------------------------------------
 4002    // ----- ExtremePredicateChecks -------------------------------------------------------------------------
 4003    // ------------------------------------------------------------------------------------------------------
 4004    #region ExtremePredicateChecks
 4005    enum CallingPosition { Positive, Negative, Neither }
 04006    static CallingPosition Invert(CallingPosition cp) {
 04007      switch (cp) {
 04008        case CallingPosition.Positive: return CallingPosition.Negative;
 04009        case CallingPosition.Negative: return CallingPosition.Positive;
 04010        default: return CallingPosition.Neither;
 4011      }
 04012    }
 4013
 4014    class FindFriendlyCalls_Visitor : ResolverTopDownVisitor<CallingPosition> {
 4015      public readonly bool IsCoContext;
 4016      public readonly bool ContinuityIsImportant;
 4017      public FindFriendlyCalls_Visitor(Resolver resolver, bool co, bool continuityIsImportant)
 04018        : base(resolver) {
 4019        Contract.Requires(resolver != null);
 04020        this.IsCoContext = co;
 04021        this.ContinuityIsImportant = continuityIsImportant;
 04022      }
 4023
 04024      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04025        if (expr is UnaryOpExpr) {
 04026          var e = (UnaryOpExpr)expr;
 04027          if (e.Op == UnaryOpExpr.Opcode.Not) {
 4028            // for the sub-parts, use Invert(cp)
 04029            cp = Invert(cp);
 04030            return true;
 4031          }
 04032        } else if (expr is BinaryExpr) {
 04033          var e = (BinaryExpr)expr;
 04034          switch (e.ResolvedOp) {
 4035            case BinaryExpr.ResolvedOpcode.And:
 4036            case BinaryExpr.ResolvedOpcode.Or:
 04037              return true;  // do the sub-parts with the same "cp"
 4038            case BinaryExpr.ResolvedOpcode.Imp:
 04039              Visit(e.E0, Invert(cp));
 04040              Visit(e.E1, cp);
 04041              return false;  // don't recurse (again) on the sub-parts
 4042            default:
 04043              break;
 4044          }
 04045        } else if (expr is NestedMatchExpr) {
 04046          var e = (NestedMatchExpr)expr;
 04047          Visit(e.Source, CallingPosition.Neither);
 04048          var theCp = cp;
 04049          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04050          return false;
 04051        } else if (expr is MatchExpr) {
 04052          var e = (MatchExpr)expr;
 04053          Visit(e.Source, CallingPosition.Neither);
 04054          var theCp = cp;
 04055          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04056          return false;
 04057        } else if (expr is ITEExpr) {
 04058          var e = (ITEExpr)expr;
 04059          Visit(e.Test, CallingPosition.Neither);
 04060          Visit(e.Thn, cp);
 04061          Visit(e.Els, cp);
 04062          return false;
 04063        } else if (expr is LetExpr) {
 04064          var e = (LetExpr)expr;
 04065          foreach (var rhs in e.RHSs) {
 04066            Visit(rhs, CallingPosition.Neither);
 04067          }
 04068          var cpBody = cp;
 04069          if (!e.Exact) {
 4070            // a let-such-that expression introduces an existential that may depend on the _k in a least/greatest predic
 04071            if (IsCoContext && cp == CallingPosition.Positive) {
 04072              cpBody = CallingPosition.Neither;
 04073            } else if (!IsCoContext && cp == CallingPosition.Negative) {
 04074              cpBody = CallingPosition.Neither;
 04075            }
 04076          }
 04077          Visit(e.Body, cpBody);
 04078          return false;
 04079        } else if (expr is QuantifierExpr) {
 04080          var e = (QuantifierExpr)expr;
 04081          Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 04082          var cpos = IsCoContext ? cp : Invert(cp);
 04083          if (ContinuityIsImportant) {
 04084            if ((cpos == CallingPosition.Positive && e is ExistsExpr) || (cpos == CallingPosition.Negative && e is Foral
 04085              if (e.Bounds.Exists(bnd => bnd == null || (bnd.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite)
 4086                // To ensure continuity of extreme predicates, don't allow calls under an existential (resp. universal) 
 4087                // for greatest (resp. least) predicates).
 04088                cp = CallingPosition.Neither;
 04089              }
 04090            }
 04091          }
 04092          Visit(e.LogicalBody(), cp);
 04093          return false;
 04094        } else if (expr is StmtExpr) {
 04095          var e = (StmtExpr)expr;
 04096          Visit(e.E, cp);
 04097          Visit(e.S, CallingPosition.Neither);
 04098          return false;
 04099        } else if (expr is ConcreteSyntaxExpression) {
 4100          // do the sub-parts with the same "cp"
 04101          return true;
 4102        }
 4103        // do the sub-parts with cp := Neither
 04104        cp = CallingPosition.Neither;
 04105        return true;
 04106      }
 4107    }
 4108
 04109    void KNatMismatchError(IToken tok, string contextName, ExtremePredicate.KType contextK, ExtremePredicate.KType calle
 04110      var hint = contextK == ExtremePredicate.KType.Unspecified ? string.Format(" (perhaps try declaring '{0}' as '{0}[n
 04111      reporter.Error(MessageSource.Resolver, tok,
 04112        "this call does not type check, because the context uses a _k parameter of type {0} whereas the callee uses a _k
 04113        contextK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04114        calleeK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04115        hint);
 04116    }
 4117
 4118    class ExtremePredicateChecks_Visitor : FindFriendlyCalls_Visitor {
 4119      readonly ExtremePredicate context;
 4120      public ExtremePredicateChecks_Visitor(Resolver resolver, ExtremePredicate context)
 04121        : base(resolver, context is GreatestPredicate, context.KNat) {
 4122        Contract.Requires(resolver != null);
 4123        Contract.Requires(context != null);
 04124        this.context = context;
 04125      }
 04126      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04127        if (expr is FunctionCallExpr) {
 04128          var e = (FunctionCallExpr)expr;
 04129          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4130            // we're looking at a recursive call
 04131            if (!(context is LeastPredicate ? e.Function is LeastPredicate : e.Function is GreatestPredicate)) {
 04132              resolver.reporter.Error(MessageSource.Resolver, e, "a recursive call from a {0} can go only to other {0}s"
 04133            } else if (context.KNat != ((ExtremePredicate)e.Function).KNat) {
 04134              resolver.KNatMismatchError(e.tok, context.Name, context.TypeOfK, ((ExtremePredicate)e.Function).TypeOfK);
 04135            } else if (cp != CallingPosition.Positive) {
 04136              var msg = string.Format("a {0} can be called recursively only in positive positions", context.WhatKind);
 04137              if (ContinuityIsImportant && cp == CallingPosition.Neither) {
 4138                // this may be inside an non-friendly quantifier
 04139                msg += string.Format(" and cannot sit inside an unbounded {0} quantifier", context is LeastPredicate ? "
 04140              } else {
 4141                // we don't care about the continuity restriction or
 4142                // the extreme-call is not inside an quantifier, so don't bother mentioning the part of existentials/uni
 04143              }
 04144              resolver.reporter.Error(MessageSource.Resolver, e, msg);
 04145            } else {
 04146              e.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 04147              resolver.reporter.Info(MessageSource.Resolver, e.tok, e.Function.Name + "#[_k - 1]");
 04148            }
 04149          }
 4150          // do the sub-parts with cp := Neither
 04151          cp = CallingPosition.Neither;
 04152          return true;
 4153        }
 04154        return base.VisitOneExpr(expr, ref cp);
 04155      }
 04156      protected override bool VisitOneStmt(Statement stmt, ref CallingPosition st) {
 04157        if (stmt is CallStmt) {
 04158          var s = (CallStmt)stmt;
 04159          if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4160            // we're looking at a recursive call
 04161            resolver.reporter.Error(MessageSource.Resolver, stmt.Tok, "a recursive call from a {0} can go only to other 
 04162          }
 4163          // do the sub-parts with the same "cp"
 04164          return true;
 04165        } else {
 04166          return base.VisitOneStmt(stmt, ref st);
 4167        }
 04168      }
 4169    }
 4170
 04171    void ExtremePredicateChecks(Expression expr, ExtremePredicate context, CallingPosition cp) {
 4172      Contract.Requires(expr != null);
 4173      Contract.Requires(context != null);
 04174      var v = new ExtremePredicateChecks_Visitor(this, context);
 04175      v.Visit(expr, cp);
 04176    }
 4177    #endregion ExtremePredicateChecks
 4178
 4179    // ------------------------------------------------------------------------------------------------------
 4180    // ----- ExtremeLemmaChecks -----------------------------------------------------------------------------
 4181    // ------------------------------------------------------------------------------------------------------
 4182    #region ExtremeLemmaChecks
 4183    class ExtremeLemmaChecks_Visitor : ResolverBottomUpVisitor {
 4184      ExtremeLemma context;
 4185      public ExtremeLemmaChecks_Visitor(Resolver resolver, ExtremeLemma context)
 04186        : base(resolver) {
 4187        Contract.Requires(resolver != null);
 4188        Contract.Requires(context != null);
 04189        this.context = context;
 04190      }
 04191      protected override void VisitOneStmt(Statement stmt) {
 04192        if (stmt is CallStmt) {
 04193          var s = (CallStmt)stmt;
 04194          if (s.Method is ExtremeLemma || s.Method is PrefixLemma) {
 4195            // all is cool
 04196          } else {
 4197            // the call goes from an extreme lemma context to a non-extreme-lemma callee
 04198            if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4199              // we're looking at a recursive call (to a non-extreme-lemma)
 04200              resolver.reporter.Error(MessageSource.Resolver, s.Tok, "a recursive call from a {0} can go only to other {
 04201            }
 04202          }
 04203        }
 04204      }
 04205      protected override void VisitOneExpr(Expression expr) {
 04206        if (expr is FunctionCallExpr) {
 04207          var e = (FunctionCallExpr)expr;
 4208          // the call goes from a greatest lemma context to a non-greatest-lemma callee
 04209          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4210            // we're looking at a recursive call (to a non-greatest-lemma)
 04211            resolver.reporter.Error(MessageSource.Resolver, e.tok, "a recursive call from a greatest lemma can go only t
 04212          }
 04213        }
 04214      }
 4215    }
 04216    void ExtremeLemmaChecks(Statement stmt, ExtremeLemma context) {
 4217      Contract.Requires(stmt != null);
 4218      Contract.Requires(context != null);
 04219      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04220      v.Visit(stmt);
 04221    }
 04222    void ExtremeLemmaChecks(Expression expr, ExtremeLemma context) {
 4223      Contract.Requires(context != null);
 04224      if (expr == null) {
 04225        return;
 4226      }
 4227
 04228      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04229      v.Visit(expr);
 04230    }
 4231    #endregion ExtremeLemmaChecks
 4232
 4233    // ------------------------------------------------------------------------------------------------------
 4234    // ----- CheckTypeCharacteristics -----------------------------------------------------------------------
 4235    // ------------------------------------------------------------------------------------------------------
 4236    #region CheckTypeCharacteristics
 50504237    void CheckTypeCharacteristics_Stmt(Statement stmt, bool isGhost) {
 4238      Contract.Requires(stmt != null);
 50504239      var v = new CheckTypeCharacteristics_Visitor(this);
 50504240      v.Visit(stmt, isGhost);
 50504241    }
 145804242    void CheckTypeCharacteristics_Expr(Expression expr, bool isGhost) {
 4243      Contract.Requires(expr != null);
 145804244      var v = new CheckTypeCharacteristics_Visitor(this);
 145804245      v.Visit(expr, isGhost);
 145804246    }
 520654247    public void CheckTypeCharacteristics_Type(IToken tok, Type type, bool isGhost) {
 4248      Contract.Requires(tok != null);
 4249      Contract.Requires(type != null);
 520654250      var v = new CheckTypeCharacteristics_Visitor(this);
 520654251      v.VisitType(tok, type, isGhost);
 520654252    }
 4253
 4254    /// <summary>
 4255    /// This visitor checks that type characteristics are respected in all (implicitly or explicitly)
 4256    /// declared types. Note that equality-support is checked only in compiled contexts.
 4257    /// In addition, this visitor checks that operations that require equality are applied to
 4258    /// types that really do support equality; this, too, is checked only in compiled contexts.
 4259    /// </summary>
 4260    class CheckTypeCharacteristics_Visitor : ResolverTopDownVisitor<bool> {
 4261      public CheckTypeCharacteristics_Visitor(Resolver resolver)
 1433904262        : base(resolver) {
 4263        Contract.Requires(resolver != null);
 716954264      }
 11988004265      protected override bool VisitOneStmt(Statement stmt, ref bool inGhostContext) {
 11988004266        if (stmt.IsGhost) {
 04267          inGhostContext = true;
 04268        }
 4269        // In the sequel, do two things:
 4270        //  * Call VisitType on any type that occurs in the statement
 4271        //  * If the statement introduces ghost components, handle those components here
 4272        //    rather than letting the default visitor handle them
 15388504273        if (stmt is VarDeclStmt) {
 3400504274          var s = (VarDeclStmt)stmt;
 20579704275          foreach (var v in s.Locals) {
 3459404276            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 3459404277          }
 11988004278        } else if (stmt is VarDeclPattern) {
 04279          var s = (VarDeclPattern)stmt;
 04280          foreach (var v in s.LocalVars) {
 04281            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 04282          }
 12338504283        } else if (stmt is AssignStmt) {
 3751004284          var s = (AssignStmt)stmt;
 3751004285          if (s.Rhs is TypeRhs tRhs) {
 04286            VisitType(tRhs.Tok, tRhs.Type, inGhostContext);
 04287          }
 8587504288        } else if (stmt is AssignSuchThatStmt) {
 04289          var s = (AssignSuchThatStmt)stmt;
 04290          Visit(Attributes.SubExpressions(s.Attributes), true);
 04291          Visit(s.Expr, inGhostContext);
 04292          foreach (var lhs in s.Lhss) {
 04293            Visit(lhs, inGhostContext);
 04294          }
 04295          return false;
 4836504296        } else if (stmt is WhileStmt) {
 04297          var s = (WhileStmt)stmt;
 4298          // all subexpressions are ghost, except the guard
 04299          Visit(s.LoopSpecificationExpressions, true);
 04300          if (s.Guard != null) {
 04301            Visit(s.Guard, inGhostContext);
 04302          }
 04303          Visit(s.SubStatements, inGhostContext);
 04304          return false;
 4836504305        } else if (stmt is AlternativeLoopStmt) {
 04306          var s = (AlternativeLoopStmt)stmt;
 4307          // all subexpressions are ghost, except the guards
 04308          Visit(s.LoopSpecificationExpressions, true);
 04309          foreach (var alt in s.Alternatives) {
 04310            Visit(alt.Guard, inGhostContext);
 04311          }
 04312          Visit(s.SubStatements, inGhostContext);
 04313          return false;
 4836504314        } else if (stmt is ForLoopStmt) {
 04315          var s = (ForLoopStmt)stmt;
 4316          // all subexpressions are ghost, except the bounds
 04317          Visit(s.LoopSpecificationExpressions, true);
 04318          Visit(s.Start, inGhostContext);
 04319          if (s.End != null) {
 04320            Visit(s.End, inGhostContext);
 04321          }
 04322          Visit(s.SubStatements, inGhostContext);
 04323          return false;
 4954404324        } else if (stmt is CallStmt) {
 117904325          var s = (CallStmt)stmt;
 117904326          CheckTypeInstantiation(s.Tok, s.Method.WhatKind, s.Method.Name, s.Method.TypeArgs, s.MethodSelect.TypeApplicat
 4327          // recursively visit all subexpressions, noting that some of them may correspond to ghost formal parameters
 117904328          Contract.Assert(s.Lhs.Count == s.Method.Outs.Count);
 766204329          for (var i = 0; i < s.Method.Outs.Count; i++) {
 176804330            Visit(s.Lhs[i], inGhostContext || s.Method.Outs[i].IsGhost);
 176804331          }
 117904332          Visit(s.Receiver, inGhostContext);
 117904333          Contract.Assert(s.Args.Count == s.Method.Ins.Count);
 1166104334          for (var i = 0; i < s.Method.Ins.Count; i++) {
 310104335            Visit(s.Args[i], inGhostContext || s.Method.Ins[i].IsGhost);
 310104336          }
 117904337          return false;
 4718604338        } else if (stmt is ForallStmt) {
 04339          var s = (ForallStmt)stmt;
 04340          foreach (var v in s.BoundVars) {
 04341            VisitType(v.Tok, v.Type, inGhostContext);
 04342          }
 4343          // do substatements and subexpressions, noting that ensures clauses are ghost
 04344          Visit(Attributes.SubExpressions(s.Attributes), true);
 04345          if (s.Range != null) {
 04346            Visit(s.Range, inGhostContext);
 04347          }
 04348          foreach (var ee in s.Ens) {
 04349            Visit(Attributes.SubExpressions(ee.Attributes), true);
 04350            Visit(ee.E, true);
 04351          }
 04352          Visit(s.SubStatements, inGhostContext);
 04353          return false;
 4718604354        } else if (stmt is ExpectStmt) {
 04355          var s = (ExpectStmt)stmt;
 04356          Visit(Attributes.SubExpressions(s.Attributes), true);
 04357          Visit(s.Expr, inGhostContext);
 04358          if (s.Message != null) {
 04359            Visit(s.Message, inGhostContext);
 04360          }
 04361          return false;
 4362        }
 11870104363        return true;
 11988004364      }
 4365
 27470654366      protected override bool VisitOneExpr(Expression expr, ref bool inGhostContext) {
 4367        // Do two things:
 4368        //  * Call VisitType on any type that occurs in the statement
 4369        //  * If the expression introduces ghost components, handle those components here
 4370        //    rather than letting the default visitor handle them
 28125954371        if (expr is BinaryExpr && !inGhostContext) {
 655304372          var e = (BinaryExpr)expr;
 655304373          var t0 = e.E0.Type.NormalizeExpand();
 655304374          var t1 = e.E1.Type.NormalizeExpand();
 655304375          switch (e.Op) {
 4376            case BinaryExpr.Opcode.Eq:
 4377            case BinaryExpr.Opcode.Neq:
 4378              // First, check some special cases that can always be compared against--for example, a datatype value (lik
 41804379              if (CanCompareWith(e.E0)) {
 4380                // that's cool
 20904381              } else if (CanCompareWith(e.E1)) {
 4382                // oh yeah!
 04383              } else if (!t0.PartiallySupportsEquality) {
 04384                resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of types t
 04385              } else if (!t1.PartiallySupportsEquality) {
 04386                resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of types t
 04387              }
 20904388              break;
 4389            default:
 634404390              switch (e.ResolvedOp) {
 4391                // Note, all operations on sets, multisets, and maps are guaranteed to work because of restrictions plac
 4392                // these types are instantiated.  (Except: This guarantee does not apply to equality on maps, because th
 4393                // of maps is not restricted, only the Domain type.  However, the equality operator is checked above.)
 4394                case BinaryExpr.ResolvedOpcode.InSeq:
 4395                case BinaryExpr.ResolvedOpcode.NotInSeq:
 4396                case BinaryExpr.ResolvedOpcode.Prefix:
 4397                case BinaryExpr.ResolvedOpcode.ProperPrefix:
 4804398                  if (!t1.SupportsEquality) {
 04399                    resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of seq
 4804400                  } else if (!t0.SupportsEquality) {
 04401                    if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.InSet || e.ResolvedOp == BinaryExpr.ResolvedOpcode.Not
 04402                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of t
 04403                    } else {
 04404                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of s
 04405                    }
 04406                  }
 4804407                  break;
 4408                default:
 629604409                  break;
 4410              }
 634404411              break;
 4412          }
 27524254413        } else if (expr is ComprehensionExpr) {
 53604414          var e = (ComprehensionExpr)expr;
 567004415          foreach (var bv in e.BoundVars) {
 135404416            VisitType(bv.tok, bv.Type, inGhostContext);
 135404417          }
 27200354418        } else if (expr is LetExpr) {
 385004419          var e = (LetExpr)expr;
 385004420          Visit(Attributes.SubExpressions(e.Attributes), true);
 770004421          if (e.Exact) {
 385004422            Contract.Assert(e.LHSs.Count == e.RHSs.Count);
 1925004423            for (var i = 0; i < e.LHSs.Count; i++) {
 4424              // The VisitPattern function visits all BoundVar's in a pattern and returns
 4425              // "true" if all variables are ghost.
 385004426              bool VisitPattern(CasePattern<BoundVar> pat, bool patternGhostContext) {
 770004427                if (pat.Var != null) {
 385004428                  VisitType(pat.tok, pat.Var.Type, patternGhostContext || pat.Var.IsGhost);
 385004429                  return pat.Var.IsGhost;
 04430                } else {
 04431                  var allGhost = true;
 04432                  Contract.Assert(pat.Ctor != null);
 04433                  Contract.Assert(pat.Ctor.Formals.Count == pat.Arguments.Count);
 04434                  for (var i = 0; i < pat.Ctor.Formals.Count; i++) {
 04435                    var formal = pat.Ctor.Formals[i];
 04436                    var arg = pat.Arguments[i];
 4437                    // don't use short-circuit booleans in the following line, because we want to visit all nested patte
 04438                    allGhost &= VisitPattern(arg, patternGhostContext || formal.IsGhost);
 04439                  }
 04440                  return allGhost;
 4441                }
 385004442              }
 4443
 385004444              var allGhosts = VisitPattern(e.LHSs[i], inGhostContext);
 385004445              Visit(e.RHSs[i], inGhostContext || allGhosts);
 385004446            }
 385004447          } else {
 04448            Contract.Assert(e.RHSs.Count == 1);
 04449            var allGhost = true;
 04450            foreach (var bv in e.BoundVars) {
 04451              if (!bv.IsGhost) {
 04452                allGhost = false;
 04453              }
 04454              VisitType(bv.tok, bv.Type, inGhostContext || bv.IsGhost);
 04455            }
 04456            Visit(e.RHSs[0], inGhostContext || allGhost);
 04457          }
 385004458          Visit(e.Body, inGhostContext);
 385004459          return false;
 26491654460        } else if (expr is MemberSelectExpr) {
 114904461          var e = (MemberSelectExpr)expr;
 141504462          if (e.Member is Function || e.Member is Method) {
 26604463            CheckTypeInstantiation(e.tok, e.Member.WhatKind, e.Member.Name, ((ICallable)e.Member).TypeArgs, e.TypeApplic
 26604464          }
 26452254465        } else if (expr is FunctionCallExpr) {
 75504466          var e = (FunctionCallExpr)expr;
 75504467          CheckTypeInstantiation(e.tok, e.Function.WhatKind, e.Function.Name, e.Function.TypeArgs, e.TypeApplication_Jus
 4468          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 75504469          Visit(e.Receiver, inGhostContext);
 75504470          Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 753404471          for (var i = 0; i < e.Args.Count; i++) {
 200804472            Visit(e.Args[i], inGhostContext || e.Function.Formals[i].IsGhost);
 200804473          }
 75504474          return false;  // we've done what there is to be done
 27785554475        } else if (expr is DatatypeValue) {
 1599204476          var e = (DatatypeValue)expr;
 4477          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 1599204478          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 12107804479          for (var i = 0; i < e.Arguments.Count; i++) {
 2969804480            Visit(e.Arguments[i], inGhostContext || e.Ctor.Formals[i].IsGhost);
 2969804481          }
 1599204482          return false;  // we've done what there is to be done
 24587154483        } else if (expr is SetDisplayExpr || expr is MultiSetDisplayExpr || expr is MapDisplayExpr || expr is SeqConstru
 25752854484                   expr is MultiSetFormingExpr || expr is StaticReceiverExpr) {
 4485          // This catches other expressions whose type may potentially be illegal
 1165704486          VisitType(expr.tok, expr.Type, inGhostContext);
 24587154487        } else if (expr is StmtExpr) {
 04488          var e = (StmtExpr)expr;
 04489          Visit(e.S, true);
 04490          Visit(e.E, inGhostContext);
 04491          return false;
 4492        }
 25410954493        return true;
 27470654494      }
 4495
 15265604496      public void VisitType(IToken tok, Type type, bool inGhostContext) {
 4497        Contract.Requires(tok != null);
 4498        Contract.Requires(type != null);
 15265604499        type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or
 23190254500        if (type is BasicType) {
 4501          // fine
 16638504502        } else if (type is SetType) {
 1372904503          var st = (SetType)type;
 1372904504          var argType = st.Arg;
 1372904505          if (!inGhostContext && !argType.SupportsEquality) {
 04506            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}set argument type must support equality (got {0}){1
 04507          }
 1372904508          VisitType(tok, argType, inGhostContext);
 4509
 8607054510        } else if (type is MultiSetType) {
 1266104511          var argType = ((MultiSetType)type).Arg;
 1266104512          if (!inGhostContext && !argType.SupportsEquality) {
 04513            resolver.reporter.Error(MessageSource.Resolver, tok, "multiset argument type must support equality (got {0})
 4514
 04515          }
 1266104516          VisitType(tok, argType, inGhostContext);
 5968054517        } else if (type is MapType) {
 04518          var mt = (MapType)type;
 04519          if (!inGhostContext && !mt.Domain.SupportsEquality) {
 04520            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}map domain type must support equality (got {0}){1}"
 04521          }
 04522          VisitType(tok, mt.Domain, inGhostContext);
 04523          VisitType(tok, mt.Range, inGhostContext);
 4524
 5755654525        } else if (type is SeqType) {
 1053704526          Type argType = ((SeqType)type).Arg;
 1053704527          VisitType(tok, argType, inGhostContext);
 4528
 8350204529        } else if (type is UserDefinedType) {
 3648254530          var udt = (UserDefinedType)type;
 3648254531          Contract.Assert(udt.ResolvedClass != null);
 3648254532          var formalTypeArgs = udt.ResolvedClass.TypeArgs;
 3648254533          Contract.Assert(formalTypeArgs != null);
 3648254534          CheckTypeInstantiation(udt.tok, "type", udt.ResolvedClass.Name, formalTypeArgs, udt.TypeArgs, inGhostContext);
 4535
 3648254536        } else if (type is TypeProxy) {
 4537          // the type was underconstrained; this is checked elsewhere, but it is not in violation of the equality-type t
 04538        } else {
 04539          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4540        }
 15265604541      }
 4542
 3868254543      void CheckTypeInstantiation(IToken tok, string what, string className, List<TypeParameter> formalTypeArgs, List<Ty
 4544        Contract.Requires(tok != null);
 4545        Contract.Requires(what != null);
 4546        Contract.Requires(className != null);
 4547        Contract.Requires(formalTypeArgs != null);
 4548        Contract.Requires(actualTypeArgs != null);
 4549        Contract.Requires(formalTypeArgs.Count == actualTypeArgs.Count);
 4550
 25456754551        for (var i = 0; i < formalTypeArgs.Count; i++) {
 5906754552          var formal = formalTypeArgs[i];
 5906754553          var actual = actualTypeArgs[i];
 5906754554          if (!CheckCharacteristics(formal.Characteristics, actual, inGhostContext, out var whatIsWrong, out var hint)) 
 04555            resolver.reporter.Error(MessageSource.Resolver, tok, "type parameter{0} ({1}) passed to {2} {3} must support
 04556              actualTypeArgs.Count == 1 ? "" : " " + i, formal.Name, what, className, whatIsWrong, actual, hint);
 04557          }
 5906754558          VisitType(tok, actual, inGhostContext);
 5906754559        }
 3868254560      }
 4561
 5906754562      bool CheckCharacteristics(TypeParameter.TypeParameterCharacteristics formal, Type actual, bool inGhostContext, out
 4563        Contract.Ensures(Contract.Result<bool>() || (Contract.ValueAtReturn(out whatIsWrong) != null && Contract.ValueAt
 5906754564        if (!inGhostContext && formal.EqualitySupport != TypeParameter.EqualitySupportValue.Unspecified && !actual.Suppo
 04565          whatIsWrong = "equality";
 04566          hint = TypeEqualityErrorMessageHint(actual);
 04567          return false;
 4568        }
 5906754569        var cl = (actual.Normalize() as UserDefinedType)?.ResolvedClass;
 5906754570        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 5906754571        if (formal.HasCompiledValue && (inGhostContext ? !actual.IsNonempty : !actual.HasCompilableValue)) {
 04572          whatIsWrong = "auto-initialization";
 04573          hint = tp == null ? "" :
 04574            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(0)', which says it can only be instanti
 04575          return false;
 4576        }
 5906754577        if (formal.IsNonempty && !actual.IsNonempty) {
 04578          whatIsWrong = "nonempty";
 04579          hint = tp == null ? "" :
 04580            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(00)', which says it can only be instant
 04581          return false;
 4582        }
 5906754583        if (formal.ContainsNoReferenceTypes && actual.MayInvolveReferences) {
 04584          whatIsWrong = "no references";
 04585          hint = tp == null ? "" :
 04586            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(!new)', which says it can only be insta
 04587          return false;
 4588        }
 5906754589        whatIsWrong = null;
 5906754590        hint = null;
 5906754591        return true;
 5906754592      }
 4593
 04594      string TypeEqualityErrorMessageHint(Type argType) {
 4595        Contract.Requires(argType != null);
 04596        var cl = (argType.Normalize() as UserDefinedType)?.ResolvedClass;
 04597        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 04598        if (tp != null) {
 04599          return string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(==)', which says it can only be in
 4600        }
 04601        return "";
 04602      }
 4603    }
 4604
 26004605    public static bool CanCompareWith(Expression expr) {
 4606      Contract.Requires(expr != null);
 52004607      if (expr.Type.SupportsEquality) {
 26004608        return true;
 4609      }
 04610      expr = expr.Resolved;
 04611      if (expr is DatatypeValue datatypeValue && !datatypeValue.Ctor.EnclosingDatatype.HasGhostVariant) {
 04612        for (var i = 0; i < datatypeValue.Ctor.Formals.Count; i++) {
 04613          if (datatypeValue.Ctor.Formals[i].IsGhost) {
 04614            return false;
 04615          } else if (!CanCompareWith(datatypeValue.Arguments[i])) {
 04616            return false;
 4617          }
 04618        }
 04619        return true;
 04620      } else if (expr is DisplayExpression) {
 04621        var e = (DisplayExpression)expr;
 04622        return e.Elements.Count == 0;
 04623      } else if (expr is MapDisplayExpr) {
 04624        var e = (MapDisplayExpr)expr;
 04625        return e.Elements.Count == 0;
 4626      }
 04627      return false;
 26004628    }
 4629
 4630    #endregion CheckTypeCharacteristics
 4631
 4632    // ------------------------------------------------------------------------------------------------------
 4633    // ----- ComputeGhostInterest ---------------------------------------------------------------------------
 4634    // ------------------------------------------------------------------------------------------------------
 4635    #region ComputeGhostInterest
 50504636    public void ComputeGhostInterest(Statement stmt, bool mustBeErasable, [CanBeNull] string proofContext, ICodeContext 
 4637      Contract.Requires(stmt != null);
 4638      Contract.Requires(codeContext != null);
 50504639      var visitor = new GhostInterestVisitor(codeContext, this, reporter, false, codeContext is Method);
 50504640      visitor.Visit(stmt, mustBeErasable, proofContext);
 50504641    }
 4642
 4643    #endregion
 4644
 4645    // ------------------------------------------------------------------------------------------------------
 4646    // ----- FillInDefaultLoopDecreases ---------------------------------------------------------------------
 4647    // ------------------------------------------------------------------------------------------------------
 4648    #region FillInDefaultLoopDecreases
 4649    class FillInDefaultLoopDecreases_Visitor : ResolverBottomUpVisitor {
 4650      readonly ICallable EnclosingMethod;
 4651      public FillInDefaultLoopDecreases_Visitor(Resolver resolver, ICallable enclosingMethod)
 50504652        : base(resolver) {
 4653        Contract.Requires(resolver != null);
 4654        Contract.Requires(enclosingMethod != null);
 25254655        EnclosingMethod = enclosingMethod;
 25254656      }
 5994004657      protected override void VisitOneStmt(Statement stmt) {
 5994004658        if (stmt is WhileStmt) {
 04659          var s = (WhileStmt)stmt;
 04660          resolver.FillInDefaultLoopDecreases(s, s.Guard, s.Decreases.Expressions, EnclosingMethod);
 5994004661        } else if (stmt is AlternativeLoopStmt) {
 04662          var s = (AlternativeLoopStmt)stmt;
 04663          resolver.FillInDefaultLoopDecreases(s, null, s.Decreases.Expressions, EnclosingMethod);
 04664        }
 5994004665      }
 4666    }
 4667    #endregion FillInDefaultLoopDecreases
 4668
 4669    // ------------------------------------------------------------------------------------------------------
 4670    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4671    // ------------------------------------------------------------------------------------------------------
 4672    #region ReportOtherAdditionalInformation_Visitor
 4673    class ReportOtherAdditionalInformation_Visitor : ResolverBottomUpVisitor {
 4674      public ReportOtherAdditionalInformation_Visitor(Resolver resolver)
 50504675        : base(resolver) {
 4676        Contract.Requires(resolver != null);
 25254677      }
 5994004678      protected override void VisitOneStmt(Statement stmt) {
 5994004679        if (stmt is ForallStmt) {
 04680          var s = (ForallStmt)stmt;
 04681          if (s.Kind == ForallStmt.BodyKind.Call) {
 04682            var cs = (CallStmt)s.S0;
 4683            // show the callee's postcondition as the postcondition of the 'forall' statement
 4684            // TODO:  The following substitutions do not correctly take into consideration variable capture; hence, what
 04685            var argsSubstMap = new Dictionary<IVariable, Expression>();  // maps formal arguments to actuals
 04686            Contract.Assert(cs.Method.Ins.Count == cs.Args.Count);
 04687            for (int i = 0; i < cs.Method.Ins.Count; i++) {
 04688              argsSubstMap.Add(cs.Method.Ins[i], cs.Args[i]);
 04689            }
 04690            var substituter = new AlphaConvertingSubstituter(cs.Receiver, argsSubstMap, new Dictionary<TypeParameter, Ty
 04691            if (!Attributes.Contains(s.Attributes, "auto_generated")) {
 04692              foreach (var ens in cs.Method.Ens) {
 04693                var p = substituter.Substitute(ens.E);  // substitute the call's actuals for the method's formals
 04694                resolver.reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(resolver.Options
 04695              }
 04696            }
 04697          }
 04698        }
 5994004699      }
 4700    }
 4701    #endregion ReportOtherAdditionalInformation_Visitor
 4702
 4703    // ------------------------------------------------------------------------------------------------------
 4704    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4705    // ------------------------------------------------------------------------------------------------------
 4706    #region CheckDividedConstructorInit
 4707    class CheckDividedConstructorInit_Visitor : ResolverTopDownVisitor<int> {
 4708      public CheckDividedConstructorInit_Visitor(Resolver resolver)
 24904709        : base(resolver) {
 4710        Contract.Requires(resolver != null);
 12454711      }
 04712      public void CheckInit(List<Statement> initStmts) {
 4713        Contract.Requires(initStmts != null);
 04714        initStmts.Iter(CheckInit);
 04715      }
 4716      /// <summary>
 4717      /// This method almost does what Visit(Statement) does, except that it handles assignments to
 4718      /// fields differently.
 4719      /// </summary>
 04720      void CheckInit(Statement stmt) {
 4721        Contract.Requires(stmt != null);
 4722        // Visit(stmt) would do:
 4723        //     stmt.SubExpressions.Iter(Visit);    (*)
 4724        //     stmt.SubStatements.Iter(Visit);     (**)
 4725        //     VisitOneStmt(stmt);                 (***)
 4726        // We may do less for (*), we always use CheckInit instead of Visit in (**), and we do (***) the same.
 04727        if (stmt is AssignStmt) {
 04728          var s = stmt as AssignStmt;
 4729          // The usual visitation of s.SubExpressions.Iter(Visit) would do the following:
 4730          //   Attributes.SubExpressions(s.Attributes).Iter(Visit);  (+)
 4731          //   Visit(s.Lhs);                                         (++)
 4732          //   s.Rhs.SubExpressions.Iter(Visit);                     (+++)
 4733          // Here, we may do less; in particular, we may omit (++).
 04734          Attributes.SubExpressions(s.Attributes).Iter(VisitExpr);  // (+)
 04735          var mse = s.Lhs as MemberSelectExpr;
 04736          if (mse != null && Expression.AsThis(mse.Obj) != null) {
 04737            if (s.Rhs is ExprRhs) {
 4738              // This is a special case we allow.  Omit s.Lhs in the recursive visits.  That is, we omit (++).
 4739              // Furthermore, because the assignment goes to a field of "this" and won't be available until after
 4740              // the "new;", we can allow certain specific (and useful) uses of "this" in the RHS.
 04741              s.Rhs.SubExpressions.Iter(LiberalRHSVisit);  // (+++)
 04742            } else {
 04743              s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04744            }
 04745          } else {
 04746            VisitExpr(s.Lhs);  // (++)
 04747            s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04748          }
 04749        } else {
 04750          stmt.SubExpressions.Iter(VisitExpr);  // (*)
 04751        }
 04752        stmt.SubStatements.Iter(CheckInit);  // (**)
 04753        int dummy = 0;
 04754        VisitOneStmt(stmt, ref dummy);  // (***)
 04755      }
 04756      void VisitExpr(Expression expr) {
 4757        Contract.Requires(expr != null);
 04758        Visit(expr, 0);
 04759      }
 04760      protected override bool VisitOneExpr(Expression expr, ref int unused) {
 04761        if (expr is MemberSelectExpr) {
 04762          var e = (MemberSelectExpr)expr;
 04763          if (e.Member.IsInstanceIndependentConstant && Expression.AsThis(e.Obj) != null) {
 04764            return false;  // don't continue the recursion
 4765          }
 04766        } else if (expr is ThisExpr && !(expr is ImplicitThisExpr_ConstructorCall)) {
 04767          resolver.reporter.Error(MessageSource.Resolver, expr.tok, "in the first division of the constructor body (befo
 04768        }
 04769        return base.VisitOneExpr(expr, ref unused);
 04770      }
 04771      void LiberalRHSVisit(Expression expr) {
 4772        Contract.Requires(expr != null);
 4773        // It is important not to allow "this" to flow into something that can be used (for compilation or
 4774        // verification purposes) before the "new;", because, to the verifier, "this" has not yet been allocated.
 4775        // The verifier is told that everything reachable from the heap is expected to be allocated and satisfy all
 4776        // the usual properties, so "this" had better not become reachable from the heap until after the "new;"
 4777        // that does the actual allocation of "this".
 4778        // Within these restrictions, we can allow the (not yet fully available) value "this" to flow into values
 4779        // stored in fields of "this".  Such values are naked occurrences of "this" and "this" occurring
 4780        // as part of constructing a value type.  Since by this rule, "this" may be part of the value stored in
 4781        // a field of "this", we must apply the same rules to uses of the values of fields of "this".
 04782        if (expr is ConcreteSyntaxExpression) {
 04783        } else if (expr is ThisExpr) {
 04784        } else if (expr is MemberSelectExpr && IsThisDotField((MemberSelectExpr)expr)) {
 04785        } else if (expr is SetDisplayExpr) {
 04786        } else if (expr is MultiSetDisplayExpr) {
 04787        } else if (expr is SeqDisplayExpr) {
 04788        } else if (expr is MapDisplayExpr) {
 04789        } else if (expr is BinaryExpr && IsCollectionOperator(((BinaryExpr)expr).ResolvedOp)) {
 04790        } else if (expr is DatatypeValue) {
 04791        } else if (expr is ITEExpr) {
 04792          var e = (ITEExpr)expr;
 04793          VisitExpr(e.Test);
 04794          LiberalRHSVisit(e.Thn);
 04795          LiberalRHSVisit(e.Els);
 04796          return;
 04797        } else {
 4798          // defer to the usual Visit
 04799          VisitExpr(expr);
 04800          return;
 4801        }
 04802        expr.SubExpressions.Iter(LiberalRHSVisit);
 04803      }
 04804      static bool IsThisDotField(MemberSelectExpr expr) {
 4805        Contract.Requires(expr != null);
 04806        return Expression.AsThis(expr.Obj) != null && expr.Member is Field;
 04807      }
 04808      static bool IsCollectionOperator(BinaryExpr.ResolvedOpcode op) {
 04809        switch (op) {
 4810          // sets:  +, *, -
 4811          case BinaryExpr.ResolvedOpcode.Union:
 4812          case BinaryExpr.ResolvedOpcode.Intersection:
 4813          case BinaryExpr.ResolvedOpcode.SetDifference:
 4814          // multisets: +, *, -
 4815          case BinaryExpr.ResolvedOpcode.MultiSetUnion:
 4816          case BinaryExpr.ResolvedOpcode.MultiSetIntersection:
 4817          case BinaryExpr.ResolvedOpcode.MultiSetDifference:
 4818          // sequences: +
 4819          case BinaryExpr.ResolvedOpcode.Concat:
 4820          // maps: +, -
 4821          case BinaryExpr.ResolvedOpcode.MapMerge:
 4822          case BinaryExpr.ResolvedOpcode.MapSubtraction:
 04823            return true;
 4824          default:
 04825            return false;
 4826        }
 04827      }
 4828    }
 4829    #endregion
 4830
 4831    // ------------------------------------------------------------------------------------------------------
 4832    // ------------------------------------------------------------------------------------------------------
 4833    // ------------------------------------------------------------------------------------------------------
 4834
 473104835    bool InferRequiredEqualitySupport(TypeParameter tp, Type type) {
 4836      Contract.Requires(tp != null);
 4837      Contract.Requires(type != null);
 4838
 473104839      type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or s
 597604840      if (type is BasicType) {
 473104841      } else if (type is SetType) {
 04842        var st = (SetType)type;
 04843        return st.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, st.Arg);
 348604844      } else if (type is MultiSetType) {
 04845        var ms = (MultiSetType)type;
 04846        return ms.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, ms.Arg);
 348604847      } else if (type is MapType) {
 04848        var mt = (MapType)type;
 04849        return mt.Domain.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, mt.Domain) || InferRequiredEqualitySu
 522904850      } else if (type is SeqType) {
 174304851        var sq = (SeqType)type;
 174304852        return InferRequiredEqualitySupport(tp, sq.Arg);
 348604853      } else if (type is UserDefinedType) {
 174304854        var udt = (UserDefinedType)type;
 174304855        List<TypeParameter> formalTypeArgs = udt.ResolvedClass.TypeArgs;
 174304856        Contract.Assert(formalTypeArgs != null);
 174304857        Contract.Assert(formalTypeArgs.Count == udt.TypeArgs.Count);
 174304858        var i = 0;
 535354859        foreach (var argType in udt.TypeArgs) {
 4154860          var formalTypeArg = formalTypeArgs[i];
 4154861          if ((formalTypeArg.SupportsEquality && argType.AsTypeParameter == tp) || InferRequiredEqualitySupport(tp, argT
 04862            return true;
 4863          }
 4154864          i++;
 4154865        }
 174304866        if (udt.ResolvedClass is TypeSynonymDecl) {
 04867          var syn = (TypeSynonymDecl)udt.ResolvedClass;
 04868          if (syn.IsRevealedInScope(Type.GetScope())) {
 04869            return InferRequiredEqualitySupport(tp, syn.RhsWithArgument(udt.TypeArgs));
 4870          }
 04871        }
 174304872      } else {
 04873        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4874      }
 298804875      return false;
 473104876    }
 4877
 4878    TopLevelDeclWithMembers currentClass;
 4879    public Method currentMethod;
 4880    readonly Scope<TypeParameter>/*!*/ allTypeParameters;
 4881    public readonly Scope<IVariable>/*!*/ scope;
 4882    Scope<Statement>/*!*/ enclosingStatementLabels;
 4883    public readonly Scope<Label>/*!*/ DominatingStatementLabels;
 4154884    List<Statement> loopStack = new List<Statement>();  // the enclosing loops (from which it is possible to break out)
 4885
 4886    /// <summary>
 4887    /// Resolves the types along .ParentTraits and fills in .ParentTraitHeads
 4888    /// </summary>
 8304889    void ResolveParentTraitTypes(TopLevelDeclWithMembers cl, Graph<TopLevelDeclWithMembers> parentRelation) {
 4890      Contract.Requires(cl != null);
 4891      Contract.Requires(currentClass == null);
 4892      Contract.Ensures(currentClass == null);
 4893
 8304894      currentClass = cl;
 8304895      allTypeParameters.PushMarker();
 8304896      ResolveTypeParameters(cl.TypeArgs, false, cl);
 24904897      foreach (var tt in cl.ParentTraits) {
 04898        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04899        ResolveType(cl.tok, tt, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOptionEnum.DontInfer, null);
 04900        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 04901          var udt = tt as UserDefinedType;
 04902          if (udt != null && udt.ResolvedClass is NonNullTypeDecl nntd && nntd.ViewAsClass is TraitDecl trait) {
 4903            // disallowing inheritance in multi module case
 04904            bool termination = true;
 04905            if (cl.EnclosingModuleDefinition == trait.EnclosingModuleDefinition || trait.IsObjectTrait || (Attributes.Co
 4906              // all is good (or the user takes responsibility for the lack of termination checking)
 04907              if (!cl.ParentTraitHeads.Contains(trait)) {
 04908                cl.ParentTraitHeads.Add(trait);
 04909                parentRelation.AddEdge(cl, trait);
 04910              }
 04911            } else {
 04912              reporter.Error(MessageSource.Resolver, udt.tok, "{0} '{1}' is in a different module than trait '{2}'. A {0
 04913            }
 04914          } else {
 04915            reporter.Error(MessageSource.Resolver, udt != null ? udt.tok : cl.tok, "a {0} can only extend traits (found 
 04916          }
 04917        }
 04918      }
 8304919      allTypeParameters.PopMarker();
 8304920      currentClass = null;
 8304921    }
 4922
 4923    /// <summary>
 4924    /// This method idempotently fills in .InheritanceInformation, .ParentFormalTypeParametersToActuals, and the
 4925    /// name->MemberDecl table for "cl" and the transitive parent traits of "cl". It also checks that every (transitive)
 4926    /// parent trait is instantiated with the same type parameters
 4927    /// The method assumes that all types along .ParentTraits have been successfully resolved and .ParentTraitHeads been
 4928    /// </summary>
 8304929    void RegisterInheritedMembers(TopLevelDeclWithMembers cl) {
 4930      Contract.Requires(cl != null);
 4931
 8304932      if (cl.ParentTypeInformation != null) {
 04933        return;
 4934      }
 8304935      cl.ParentTypeInformation = new TopLevelDeclWithMembers.InheritanceInformationClass();
 4936
 4937      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the immediate parent traits
 24904938      foreach (var tt in cl.ParentTraits) {
 04939        var udt = (UserDefinedType)tt;
 04940        var nntd = (NonNullTypeDecl)udt.ResolvedClass;
 04941        var trait = (TraitDecl)nntd.ViewAsClass;
 04942        cl.ParentTypeInformation.Record(trait, udt);
 04943        Contract.Assert(trait.TypeArgs.Count == udt.TypeArgs.Count);
 04944        for (var i = 0; i < trait.TypeArgs.Count; i++) {
 4945          // there may be duplciate parent traits, which haven't been checked for yet, so add mapping only for the first
 04946          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(trait.TypeArgs[i])) {
 04947            cl.ParentFormalTypeParametersToActuals.Add(trait.TypeArgs[i], udt.TypeArgs[i]);
 04948          }
 04949        }
 04950      }
 4951
 4952      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the transitive parent traits
 24904953      foreach (var trait in cl.ParentTraitHeads) {
 4954        // make sure the parent trait has been processed; then, incorporate its inheritance information
 04955        RegisterInheritedMembers(trait);
 04956        cl.ParentTypeInformation.Extend(trait, trait.ParentTypeInformation, cl.ParentFormalTypeParametersToActuals);
 04957        foreach (var entry in trait.ParentFormalTypeParametersToActuals) {
 04958          var v = entry.Value.Subst(cl.ParentFormalTypeParametersToActuals);
 04959          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(entry.Key)) {
 04960            cl.ParentFormalTypeParametersToActuals.Add(entry.Key, v);
 04961          }
 04962        }
 04963      }
 4964
 4965      // Check that every (transitive) parent trait is instantiated with the same type parameters
 24904966      foreach (var group in cl.ParentTypeInformation.GetTypeInstantiationGroups()) {
 04967        Contract.Assert(1 <= group.Count);
 04968        var ty = group[0].Item1;
 04969        for (var i = 1; i < group.Count; i++) {
 04970          if (!group.GetRange(0, i).Exists(pair => pair.Item1.Equals(group[i].Item1))) {
 04971            var via0 = group[0].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[0].Item2, traitDecl => traitDecl.Nam
 04972            var via1 = group[i].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[i].Item2, traitDecl => traitDecl.Nam
 04973            reporter.Error(MessageSource.Resolver, cl.tok,
 04974              "duplicate trait parents with the same head type must also have the same type arguments; got {0}{1} and {2
 04975              ty, via0, group[i].Item1, via1);
 04976          }
 04977        }
 04978      }
 4979
 4980      // Update the name->MemberDecl table for the class. Report an error if the same name refers to more than one membe
 4981      // except when such duplication is purely that one member, say X, is inherited and the other is an override of X.
 8304982      var inheritedMembers = new Dictionary<string, MemberDecl>();
 24904983      foreach (var trait in cl.ParentTraitHeads) {
 04984        foreach (var traitMember in classMembers[trait].Values) {  // TODO: rather than using .Values, it would be nice 
 04985          if (!inheritedMembers.TryGetValue(traitMember.Name, out var prevMember)) {
 4986            // record "traitMember" as an inherited member
 04987            inheritedMembers.Add(traitMember.Name, traitMember);
 04988          } else if (traitMember == prevMember) {
 4989            // same member, inherited two different ways
 04990          } else if (traitMember.Overrides(prevMember)) {
 4991            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "traitMember" is an o
 04992            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4993            // re-map "traitMember.Name" to point to the overriding member
 04994            inheritedMembers[traitMember.Name] = traitMember;
 04995          } else if (prevMember.Overrides(traitMember)) {
 4996            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "prevMember" is an ov
 04997            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4998            // keep the mapping to "prevMember"
 04999          } else {
 5000            // "prevMember" and "traitMember" refer to different members (with the same name)
 05001            reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' inherits a member named '{2}' from both traits '{3
 05002              cl.WhatKind, cl.Name, traitMember.Name, prevMember.EnclosingClass.Name, traitMember.EnclosingClass.Name);
 05003          }
 05004        }
 05005      }
 5006      // Incorporate the inherited members into the name->MemberDecl mapping of "cl"
 8305007      var members = classMembers[cl];
 24905008      foreach (var entry in inheritedMembers) {
 05009        var name = entry.Key;
 05010        var traitMember = entry.Value;
 05011        if (!members.TryGetValue(name, out var clMember)) {
 05012          members.Add(name, traitMember);
 05013        } else {
 05014          Contract.Assert(clMember.EnclosingClass == cl);  // sanity check
 05015          Contract.Assert(clMember.OverriddenMember == null);  // sanity check
 05016          clMember.OverriddenMember = traitMember;
 05017        }
 05018      }
 8305019    }
 5020
 5021    /// <summary>
 5022    /// Assumes type parameters have already been pushed
 5023    /// </summary>
 8305024    void ResolveClassMemberTypes(TopLevelDeclWithMembers cl) {
 5025      Contract.Requires(cl != null);
 5026      Contract.Requires(currentClass == null);
 5027      Contract.Ensures(currentClass == null);
 8305028      currentClass = cl;
 5029
 564005030      foreach (MemberDecl member in cl.Members) {
 179705031        member.EnclosingClass = cl;
 179705032        if (member is Field) {
 05033          if (member is ConstantField) {
 05034            var m = (ConstantField)member;
 05035            ResolveType(member.tok, ((Field)member).Type, m, ResolveTypeOptionEnum.DontInfer, null);
 05036          } else {
 5037            // In the following, we pass in a NoContext, because any cycle formed by a redirecting-type constraints woul
 5038            // dereference the heap, and such constraints are not allowed to dereference the heap so an error will be pr
 5039            // even if we don't detect this cycle.
 05040            ResolveType(member.tok, ((Field)member).Type, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOption
 05041          }
 308905042        } else if (member is Function) {
 129205043          var f = (Function)member;
 129205044          var ec = reporter.Count(ErrorLevel.Error);
 129205045          allTypeParameters.PushMarker();
 129205046          ResolveTypeParameters(f.TypeArgs, true, f);
 129205047          ResolveFunctionSignature(f);
 129205048          allTypeParameters.PopMarker();
 129205049          if (f is ExtremePredicate && ec == reporter.Count(ErrorLevel.Error)) {
 05050            var ff = ((ExtremePredicate)f).PrefixPredicate;  // note, may be null if there was an error before the prefi
 05051            if (ff != null) {
 05052              ff.EnclosingClass = cl;
 05053              allTypeParameters.PushMarker();
 05054              ResolveTypeParameters(ff.TypeArgs, true, ff);
 05055              ResolveFunctionSignature(ff);
 05056              allTypeParameters.PopMarker();
 05057            }
 05058          }
 129205059          if (f.ByMethodDecl != null) {
 05060            f.ByMethodDecl.EnclosingClass = cl;
 05061          }
 5062
 230205063        } else if (member is Method) {
 50505064          var m = (Method)member;
 50505065          var ec = reporter.Count(ErrorLevel.Error);
 50505066          allTypeParameters.PushMarker();
 50505067          ResolveTypeParameters(m.TypeArgs, true, m);
 50505068          ResolveMethodSignature(m);
 50505069          allTypeParameters.PopMarker();
 50505070          if (m is ExtremeLemma com && com.PrefixLemma != null && ec == reporter.Count(ErrorLevel.Error)) {
 05071            var mm = com.PrefixLemma;
 5072            // resolve signature of the prefix lemma
 05073            mm.EnclosingClass = cl;
 05074            allTypeParameters.PushMarker();
 05075            ResolveTypeParameters(mm.TypeArgs, true, mm);
 05076            ResolveMethodSignature(mm);
 05077            allTypeParameters.PopMarker();
 05078          }
 5079
 50505080        } else {
 05081          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 5082        }
 179705083      }
 5084
 8305085      currentClass = null;
 8305086    }
 5087
 5088    /// <summary>
 5089    /// This method checks the rules for inherited and overridden members. It also populates .InheritedMembers with the
 5090    /// non-static members that are inherited from parent traits.
 5091    /// </summary>
 8305092    void InheritedTraitMembers(TopLevelDeclWithMembers cl) {
 5093      Contract.Requires(cl != null);
 5094      Contract.Requires(cl.ParentTypeInformation != null);
 5095
 564005096      foreach (var member in classMembers[cl].Values) {
 179705097        if (member is PrefixPredicate || member is PrefixLemma) {
 5098          // these are handled with the corresponding extreme predicate/lemma
 05099          continue;
 5100        }
 179705101        if (member.EnclosingClass != cl) {
 5102          // The member is the one inherited from a trait (and the class does not itself define a member with this name)
 5103          // is fine for fields and for functions and methods with bodies. However, if "cl" is not itself a trait, then 
 5104          // or method, "cl" is required to at least redeclare the member with its signature.  (It should also provide a
 5105          // but that will be checked by the verifier.  And it should also have a body, but that will be checked by the 
 05106          if (member.IsStatic) {
 5107            // nothing to do
 05108          } else {
 05109            cl.InheritedMembers.Add(member);
 05110            if (member is Field || (member as Function)?.Body != null || (member as Method)?.Body != null) {
 5111              // member is a field or a fully defined function or method
 05112            } else if (cl is TraitDecl) {
 5113              // there are no expectations that a field needs to repeat the signature of inherited body-less members
 05114            } else if (Attributes.Contains(member.Attributes, "extern")) {
 5115              // Extern functions do not need to be reimplemented.
 5116              // TODO: When `:extern` is separated from `:compile false`, this should become `:compile false`.
 05117            } else if (member is Lemma && Attributes.Contains(member.Attributes, "opaque_reveal")) {
 5118              // reveal lemmas do not need to be reimplemented
 05119            } else {
 05120              reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' does not implement trait {2} '{3}.{4}'", cl.What
 05121            }
 05122          }
 05123          continue;
 5124        }
 359405125        if (member.OverriddenMember == null) {
 5126          // this member has nothing to do with the parent traits
 179705127          continue;
 5128        }
 5129
 05130        var traitMember = member.OverriddenMember;
 05131        var trait = traitMember.EnclosingClass;
 05132        if (traitMember.IsStatic) {
 05133          reporter.Error(MessageSource.Resolver, member.tok, "static {0} '{1}' is inherited from trait '{2}' and is not 
 05134            traitMember.WhatKind, traitMember.Name, trait.Name);
 05135        } else if (member.IsStatic) {
 05136          reporter.Error(MessageSource.Resolver, member.tok, "static member '{0}' overrides non-static member in trait '
 05137        } else if (traitMember is Field) {
 5138          // The class is not allowed to do anything with the field other than silently inherit it.
 05139          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' is inherited from trait '{2}' and is not allowed
 05140        } else if ((traitMember as Function)?.Body != null || (traitMember as Method)?.Body != null) {
 5141          // the overridden member is a fully defined function or method, so the class is not allowed to do anything wit
 05142          reporter.Error(MessageSource.Resolver, member.tok, "fully defined {0} '{1}' is inherited from trait '{2}' and 
 05143            traitMember.WhatKind, traitMember.Name, trait.Name);
 05144        } else if (member is Method != traitMember is Method ||
 05145                   member is Lemma != traitMember is Lemma ||
 05146                   member is TwoStateLemma != traitMember is TwoStateLemma ||
 05147                   member is LeastLemma != traitMember is LeastLemma ||
 05148                   member is GreatestLemma != traitMember is GreatestLemma ||
 05149                   member is Function != traitMember is Function ||
 05150                   member is TwoStateFunction != traitMember is TwoStateFunction ||
 05151                   member is LeastPredicate != traitMember is LeastPredicate ||
 05152                   member is GreatestPredicate != traitMember is GreatestPredicate) {
 05153          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' in '{2}' can only be overridden by a {0} (got {3
 05154        } else if (member.IsGhost != traitMember.IsGhost) {
 05155          reporter.Error(MessageSource.Resolver, member.tok, "overridden {0} '{1}' in '{2}' has different ghost/compiled
 05156            traitMember.WhatKind, traitMember.Name, cl.Name, trait.Name);
 05157        } else {
 5158          // Copy trait member's extern attribute onto class member if class does not provide one
 05159          if (!Attributes.Contains(member.Attributes, "extern") && Attributes.Contains(traitMember.Attributes, "extern")
 05160            var traitExternArgs = Attributes.FindExpressions(traitMember.Attributes, "extern");
 05161            member.Attributes = new Attributes("extern", traitExternArgs, member.Attributes);
 05162          }
 5163
 05164          if (traitMember is Method) {
 05165            var classMethod = (Method)member;
 05166            var traitMethod = (Method)traitMember;
 05167            classMethod.OverriddenMethod = traitMethod;
 5168
 05169            CheckOverride_MethodParameters(classMethod, traitMethod, cl.ParentFormalTypeParametersToActuals);
 5170
 05171            var traitMethodAllowsNonTermination = Contract.Exists(traitMethod.Decreases.Expressions, e => e is WildcardE
 05172            var classMethodAllowsNonTermination = Contract.Exists(classMethod.Decreases.Expressions, e => e is WildcardE
 05173            if (classMethodAllowsNonTermination && !traitMethodAllowsNonTermination) {
 05174              reporter.Error(MessageSource.Resolver, classMethod.tok, "not allowed to override a terminating method with
 05175            }
 5176
 05177          } else if (traitMember is Function) {
 05178            var classFunction = (Function)member;
 05179            var traitFunction = (Function)traitMember;
 05180            classFunction.OverriddenFunction = traitFunction;
 5181
 05182            CheckOverride_FunctionParameters(classFunction, traitFunction, cl.ParentFormalTypeParametersToActuals);
 5183
 05184          } else {
 05185            Contract.Assert(false); // unexpected member
 05186          }
 05187        }
 05188      }
 8305189    }
 5190
 05191    public void CheckOverride_FunctionParameters(Function nw, Function old, Dictionary<TypeParameter, Type> classTypeMap
 5192      Contract.Requires(nw != null);
 5193      Contract.Requires(old != null);
 5194      Contract.Requires(classTypeMap != null);
 5195
 05196      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "function", classTypeMap);
 05197      if (nw is ExtremePredicate nwFix && old is ExtremePredicate oldFix && nwFix.KNat != oldFix.KNat) {
 05198        reporter.Error(MessageSource.Resolver, nw,
 05199          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05200          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05201      }
 05202      CheckOverride_ResolvedParameters(nw.tok, old.Formals, nw.Formals, nw.Name, "function", "parameter", typeMap);
 05203      var oldResultType = old.ResultType.Subst(typeMap);
 05204      if (!nw.ResultType.Equals(oldResultType, true)) {
 05205        reporter.Error(MessageSource.Resolver, nw, "the result type of function '{0}' ({1}) differs from that in the ove
 05206          nw.Name, nw.ResultType, oldResultType);
 05207      }
 05208    }
 5209
 05210    public void CheckOverride_MethodParameters(Method nw, Method old, Dictionary<TypeParameter, Type> classTypeMap) {
 5211      Contract.Requires(nw != null);
 5212      Contract.Requires(old != null);
 5213      Contract.Requires(classTypeMap != null);
 05214      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "method", classTypeMap);
 05215      if (nw is ExtremeLemma nwFix && old is ExtremeLemma oldFix && nwFix.KNat != oldFix.KNat) {
 05216        reporter.Error(MessageSource.Resolver, nw,
 05217          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05218          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05219      }
 05220      CheckOverride_ResolvedParameters(nw.tok, old.Ins, nw.Ins, nw.Name, "method", "in-parameter", typeMap);
 05221      CheckOverride_ResolvedParameters(nw.tok, old.Outs, nw.Outs, nw.Name, "method", "out-parameter", typeMap);
 05222    }
 5223
 05224    private Dictionary<TypeParameter, Type> CheckOverride_TypeParameters(IToken tok, List<TypeParameter> old, List<TypeP
 5225      Contract.Requires(tok != null);
 5226      Contract.Requires(old != null);
 5227      Contract.Requires(nw != null);
 5228      Contract.Requires(name != null);
 5229      Contract.Requires(thing != null);
 05230      var typeMap = old.Count == 0 ? classTypeMap : new Dictionary<TypeParameter, Type>(classTypeMap);
 05231      if (old.Count != nw.Count) {
 05232        reporter.Error(MessageSource.Resolver, tok,
 05233          "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than in the overridden 
 05234      } else {
 05235        for (int i = 0; i < old.Count; i++) {
 05236          var o = old[i];
 05237          var n = nw[i];
 05238          typeMap.Add(o, new UserDefinedType(tok, n));
 5239          // Check type characteristics
 05240          if (o.Characteristics.EqualitySupport != TypeParameter.EqualitySupportValue.InferredRequired && o.Characterist
 05241            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05242          }
 05243          if (o.Characteristics.HasCompiledValue != n.Characteristics.HasCompiledValue) {
 05244            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05245          } else if (o.Characteristics.IsNonempty != n.Characteristics.IsNonempty) {
 05246            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05247          }
 05248          if (o.Characteristics.ContainsNoReferenceTypes != n.Characteristics.ContainsNoReferenceTypes) {
 05249            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the no-referenc
 05250          }
 5251
 05252        }
 05253      }
 05254      return typeMap;
 05255    }
 5256
 05257    private void CheckOverride_ResolvedParameters(IToken tok, List<Formal> old, List<Formal> nw, string name, string thi
 5258      Contract.Requires(tok != null);
 5259      Contract.Requires(old != null);
 5260      Contract.Requires(nw != null);
 5261      Contract.Requires(name != null);
 5262      Contract.Requires(thing != null);
 5263      Contract.Requires(parameterKind != null);
 5264      Contract.Requires(typeMap != null);
 05265      if (old.Count != nw.Count) {
 05266        reporter.Error(MessageSource.Resolver, tok, "{0} '{1}' is declared with a different number of {2} ({3} instead o
 05267          thing, name, parameterKind, nw.Count, old.Count);
 05268      } else {
 05269        for (int i = 0; i < old.Count; i++) {
 05270          var o = old[i];
 05271          var n = nw[i];
 05272          if (!o.IsGhost && n.IsGhost) {
 05273            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05274              parameterKind, n.Name, thing, name);
 05275          } else if (o.IsGhost && !n.IsGhost) {
 05276            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05277              parameterKind, n.Name, thing, name);
 05278          } else if (!o.IsOld && n.IsOld) {
 05279            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05280              parameterKind, n.Name, thing, name);
 05281          } else if (o.IsOld && !n.IsOld) {
 05282            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05283              parameterKind, n.Name, thing, name);
 05284          } else if (!o.IsOlder && n.IsOlder) {
 05285            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05286              parameterKind, n.Name, thing, name);
 05287          } else if (o.IsOlder && !n.IsOlder) {
 05288            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05289              parameterKind, n.Name, thing, name);
 05290          } else {
 05291            var oo = o.Type.Subst(typeMap);
 05292            if (!n.Type.Equals(oo, true)) {
 05293              reporter.Error(MessageSource.Resolver, n.tok,
 05294                "the type of {0} '{1}' is different from the type of the corresponding {0} in trait {2} ('{3}' instead o
 05295                parameterKind, n.Name, thing, n.Type, oo);
 05296            }
 05297          }
 05298        }
 05299      }
 05300    }
 5301
 5302    /// <summary>
 5303    /// Check that the SCC of 'startingPoint' can be carved up into stratospheres in such a way that each
 5304    /// datatype has some value that can be constructed from datatypes in lower stratospheres only.
 5305    /// The algorithm used here is quadratic in the number of datatypes in the SCC.  Since that number is
 5306    /// deemed to be rather small, this seems okay.
 5307    ///
 5308    /// As a side effect of this checking, the GroundingCtor field is filled in (for every inductive datatype
 5309    /// that passes the check).  It may be that several constructors could be used as the default, but
 5310    /// only the first one encountered as recorded.  This particular choice is slightly more than an
 5311    /// implementation detail, because it affects how certain cycles among inductive datatypes (having
 5312    /// to do with the types used to instantiate type parameters of datatypes) are used.
 5313    ///
 5314    /// The role of the SCC here is simply to speed up this method.  It would still be correct if the
 5315    /// equivalence classes in the given SCC were unions of actual SCC's.  In particular, this method
 5316    /// would still work if "dependencies" consisted of one large SCC containing all the inductive
 5317    /// datatypes in the module.
 5318    /// </summary>
 05319    void SccStratosphereCheck(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5320      Contract.Requires(startingPoint != null);
 5321      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5322
 05323      var scc = dependencies.GetSCC(startingPoint);
 05324      int totalCleared = 0;
 05325      while (true) {
 05326        int clearedThisRound = 0;
 05327        foreach (var dt in scc) {
 05328          if (dt.GroundingCtor != null) {
 5329            // previously cleared
 05330          } else if (ComputeGroundingCtor(dt)) {
 05331            Contract.Assert(dt.GroundingCtor != null);  // should have been set by the successful call to StratosphereCh
 05332            clearedThisRound++;
 05333            totalCleared++;
 05334          }
 05335        }
 05336        if (totalCleared == scc.Count) {
 5337          // all is good
 05338          return;
 05339        } else if (clearedThisRound != 0) {
 5340          // some progress was made, so let's keep going
 05341        } else {
 5342          // whatever is in scc-cleared now failed to pass the test
 05343          foreach (var dt in scc) {
 05344            if (dt.GroundingCtor == null) {
 05345              reporter.Error(MessageSource.Resolver, dt, "because of cyclic dependencies among constructor argument type
 05346            }
 05347          }
 05348          return;
 5349        }
 05350      }
 05351    }
 5352
 5353    /// <summary>
 5354    /// Check that the datatype has some constructor all whose argument types can be constructed.
 5355    /// Returns 'true' and sets dt.GroundingCtor if that is the case.
 5356    /// </summary>
 05357    bool ComputeGroundingCtor(IndDatatypeDecl dt) {
 5358      Contract.Requires(dt != null);
 5359      Contract.Requires(dt.GroundingCtor == null);  // the intention is that this method be called only when GroundingCt
 5360      Contract.Ensures(!Contract.Result<bool>() || dt.GroundingCtor != null);
 5361
 5362      // Stated differently, check that there is some constuctor where no argument type goes to the same stratum.
 05363      DatatypeCtor groundingCtor = null;
 05364      ISet<TypeParameter> lastTypeParametersUsed = null;
 05365      foreach (DatatypeCtor ctor in dt.Ctors) {
 05366        var typeParametersUsed = new HashSet<TypeParameter>();
 05367        foreach (Formal p in ctor.Formals) {
 05368          if (!CheckCanBeConstructed(p.Type, typeParametersUsed)) {
 5369            // the argument type (has a component which) is not yet known to be constructable
 05370            goto NEXT_OUTER_ITERATION;
 5371          }
 05372        }
 5373        // this constructor satisfies the requirements, check to see if it is a better fit than the
 5374        // one found so far. Here, "better" means
 5375        //   * a ghost constructor is better than a non-ghost constructor
 5376        //   * among those, a constructor with fewer type arguments is better
 5377        //   * among those, the first one is preferred.
 05378        if (groundingCtor == null || (!groundingCtor.IsGhost && ctor.IsGhost) || typeParametersUsed.Count < lastTypePara
 05379          groundingCtor = ctor;
 05380          lastTypeParametersUsed = typeParametersUsed;
 05381        }
 5382
 05383      NEXT_OUTER_ITERATION: { }
 05384      }
 5385
 05386      if (groundingCtor != null) {
 05387        dt.GroundingCtor = groundingCtor;
 05388        dt.TypeParametersUsedInConstructionByGroundingCtor = new bool[dt.TypeArgs.Count];
 05389        for (int i = 0; i < dt.TypeArgs.Count; i++) {
 05390          dt.TypeParametersUsedInConstructionByGroundingCtor[i] = lastTypeParametersUsed.Contains(dt.TypeArgs[i]);
 05391        }
 05392        return true;
 5393      }
 5394
 5395      // no constructor satisfied the requirements, so this is an illegal datatype declaration
 05396      return false;
 05397    }
 5398
 05399    bool CheckCanBeConstructed(Type type, ISet<TypeParameter> typeParametersUsed) {
 05400      type = type.NormalizeExpandKeepConstraints();
 05401      if (type is BasicType) {
 5402        // values of primitive types can always be constructed
 05403        return true;
 05404      } else if (type is CollectionType) {
 5405        // values of collection types can always be constructed
 05406        return true;
 5407      }
 5408
 05409      var udt = (UserDefinedType)type;
 05410      var cl = udt.ResolvedClass;
 05411      Contract.Assert(cl != null);
 05412      if (cl is TypeParameter) {
 5413        // treat a type parameter like a ground type
 05414        typeParametersUsed.Add((TypeParameter)cl);
 05415        return true;
 05416      } else if (cl is AbstractTypeDecl) {
 5417        // an opaque is like a ground type
 05418        return true;
 05419      } else if (cl is InternalTypeSynonymDecl) {
 5420        // a type exported as opaque from another module is like a ground type
 05421        return true;
 05422      } else if (cl is NewtypeDecl) {
 5423        // values of a newtype can be constructed
 05424        return true;
 05425      } else if (cl is SubsetTypeDecl) {
 05426        var td = (SubsetTypeDecl)cl;
 05427        if (td.Witness != null) {
 5428          // a witness exists, but may depend on type parameters
 05429          type.AddFreeTypeParameters(typeParametersUsed);
 05430          return true;
 05431        } else if (td.WitnessKind == SubsetTypeDecl.WKind.Special) {
 5432          // WKind.Special is only used with -->, ->, and non-null types:
 05433          Contract.Assert(ArrowType.IsPartialArrowTypeName(td.Name) || ArrowType.IsTotalArrowTypeName(td.Name) || td is 
 05434          if (ArrowType.IsTotalArrowTypeName(td.Name)) {
 05435            return CheckCanBeConstructed(udt.TypeArgs.Last(), typeParametersUsed);
 05436          } else {
 05437            return true;
 5438          }
 05439        } else {
 05440          return CheckCanBeConstructed(td.RhsWithArgument(udt.TypeArgs), typeParametersUsed);
 5441        }
 05442      } else if (cl is ClassDecl) {
 5443        // null is a value for this possibly-null type
 05444        return true;
 05445      } else if (cl is CoDatatypeDecl) {
 5446        // may depend on type parameters
 05447        type.AddFreeTypeParameters(typeParametersUsed);
 05448        return true;
 5449      }
 5450
 05451      var dependee = type.AsIndDatatype;
 05452      Contract.Assert(dependee != null);
 05453      if (dependee.GroundingCtor == null) {
 5454        // the type is an inductive datatype that we don't yet know how to construct
 05455        return false;
 5456      }
 5457      // also check the type arguments of the inductive datatype
 05458      Contract.Assert(udt.TypeArgs.Count == dependee.TypeParametersUsedInConstructionByGroundingCtor.Length);
 05459      var i = 0;
 05460      foreach (var ta in udt.TypeArgs) {
 05461        if (dependee.TypeParametersUsedInConstructionByGroundingCtor[i] && !CheckCanBeConstructed(ta, typeParametersUsed
 05462          return false;
 5463        }
 05464        i++;
 05465      }
 05466      return true;
 05467    }
 5468
 05469    void DetermineEqualitySupport(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5470      Contract.Requires(startingPoint != null);
 5471      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5472
 05473      var scc = dependencies.GetSCC(startingPoint);
 5474
 05475      void MarkSCCAsNotSupportingEquality() {
 05476        foreach (var ddtt in scc) {
 05477          ddtt.EqualitySupport = IndDatatypeDecl.ES.Never;
 05478        }
 05479      }
 5480
 5481      // Look for conditions that make the whole SCC incapable of providing the equality operation:
 5482      //   * a datatype in the SCC has a ghost constructor
 5483      //   * a parameter of an inductive datatype in the SCC is ghost
 5484      //   * the type of a parameter of an inductive datatype in the SCC does not support equality
 05485      foreach (var dt in scc) {
 05486        Contract.Assume(dt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed);
 05487        foreach (var ctor in dt.Ctors) {
 05488          if (ctor.IsGhost) {
 05489            MarkSCCAsNotSupportingEquality();
 05490            return;  // we are done
 5491          }
 05492          foreach (var arg in ctor.Formals) {
 05493            var anotherIndDt = arg.Type.AsIndDatatype;
 05494            if (arg.IsGhost ||
 05495                (anotherIndDt != null && anotherIndDt.EqualitySupport == IndDatatypeDecl.ES.Never) ||
 05496                arg.Type.IsCoDatatype ||
 05497                arg.Type.IsArrowType) {
 5498              // arg.Type is known never to support equality
 05499              MarkSCCAsNotSupportingEquality();
 05500              return;  // we are done
 5501            }
 05502          }
 05503        }
 05504      }
 5505
 5506      // Now for the more involved case:  we need to determine which type parameters determine equality support for each
 5507      // We start by seeing where each datatype's type parameters are used in a place known to determine equality suppor
 05508      bool thingsChanged = false;
 05509      foreach (var dt in scc) {
 05510        if (dt.TypeArgs.Count == 0) {
 5511          // if the datatype has no type parameters, we certainly won't find any type parameters being used in the argum
 05512          continue;
 5513        }
 05514        foreach (var ctor in dt.Ctors) {
 05515          foreach (var arg in ctor.Formals) {
 05516            var typeArg = arg.Type.AsTypeParameter;
 05517            if (typeArg != null) {
 05518              typeArg.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05519              thingsChanged = true;
 05520            } else {
 05521              var otherDt = arg.Type.AsIndDatatype;
 05522              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.ConsultTypeArguments) {  // datatype 
 05523                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05524                var i = 0;
 05525                foreach (var otherTp in otherDt.TypeArgs) {
 05526                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05527                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05528                    if (tp != null) {
 05529                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05530                      thingsChanged = true;
 05531                    }
 05532                  }
 05533                }
 05534              }
 05535            }
 05536          }
 05537        }
 05538      }
 5539      // Then we propagate this information up through the SCC
 05540      while (thingsChanged) {
 05541        thingsChanged = false;
 05542        foreach (var dt in scc) {
 05543          if (dt.TypeArgs.Count == 0) {
 5544            // if the datatype has no type parameters, we certainly won't find any type parameters being used in the arg
 05545            continue;
 5546          }
 05547          foreach (var ctor in dt.Ctors) {
 05548            foreach (var arg in ctor.Formals) {
 05549              var otherDt = arg.Type.AsIndDatatype;
 05550              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed) { // otherDt lives in
 05551                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05552                var i = 0;
 05553                foreach (var otherTp in otherDt.TypeArgs) {
 05554                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05555                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05556                    if (tp != null && !tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05557                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05558                      thingsChanged = true;
 05559                    }
 05560                  }
 05561                  i++;
 05562                }
 05563              }
 05564            }
 05565          }
 05566        }
 05567      }
 5568      // Now that we have computed the .NecessaryForEqualitySupportOfSurroundingInductiveDatatype values, mark the datat
 5569      // where equality support should be checked by looking at the type arguments.
 05570      foreach (var dt in scc) {
 05571        dt.EqualitySupport = IndDatatypeDecl.ES.ConsultTypeArguments;
 05572      }
 05573    }
 5574
 5575    /// <summary>
 5576    /// Check to see if the attribute is one that is supported by Dafny.  What check performed here is,
 5577    /// unfortunately, just an approximation, since the usage rules of a particular attribute is checked
 5578    /// elsewhere (for example, in the compiler or verifier).  It would be nice to improve this.
 5579    /// </summary>
 05580    bool IsRecognizedAttribute(UserSuppliedAttributes a, IAttributeBearingDeclaration host) {
 5581      Contract.Requires(a != null);
 5582      Contract.Requires(host != null);
 05583      switch (a.Name) {
 5584        case "opaque":
 05585          return host is Function && !(host is ExtremePredicate);
 5586        case "trigger":
 05587          return host is ComprehensionExpr || host is SetComprehension || host is MapComprehension;
 5588        case "timeLimit":
 5589        case "timeLimitMultiplier":
 05590          return host is TopLevelDecl;
 5591        case "tailrecursive":
 05592          return host is Method && !((Method)host).IsGhost;
 5593        case "autocontracts":
 05594          return host is ClassDecl;
 5595        case "autoreq":
 05596          return host is Function;
 5597        case "abstemious":
 05598          return host is Function;
 5599        case "options":
 05600          return host is ModuleDefinition;
 5601        default:
 05602          return false;
 5603      }
 05604    }
 5605
 4494405606    public void ScopePushAndReport(Scope<IVariable> scope, IVariable v, string kind) {
 5607      Contract.Requires(scope != null);
 5608      Contract.Requires(v != null);
 5609      Contract.Requires(kind != null);
 4494405610      ScopePushAndReport(scope, v.Name, v, v.Tok, kind);
 4494405611    }
 5612
 4494405613    void ScopePushAndReport<Thing>(Scope<Thing> scope, string name, Thing thing, IToken tok, string kind) where Thing : 
 5614      Contract.Requires(scope != null);
 5615      Contract.Requires(name != null);
 5616      Contract.Requires(thing != null);
 5617      Contract.Requires(tok != null);
 5618      Contract.Requires(kind != null);
 4494405619      var r = scope.Push(name, thing);
 4494405620      switch (r) {
 5621        case Scope<Thing>.PushResult.Success:
 4494405622          break;
 5623        case Scope<Thing>.PushResult.Duplicate:
 05624          reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Duplicate {0} name: {1}", kind, name);
 05625          break;
 5626        case Scope<Thing>.PushResult.Shadow:
 05627          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Shadowed {0} name: {1}", kind, name);
 05628          break;
 5629      }
 4494405630    }
 5631
 5632    /// <summary>
 5633    /// Assumes type parameters have already been pushed
 5634    /// </summary>
 137505635    void ResolveFunctionSignature(Function f) {
 5636      Contract.Requires(f != null);
 137505637      scope.PushMarker();
 137505638      if (f.SignatureIsOmitted) {
 05639        reporter.Error(MessageSource.Resolver, f, "function signature can be omitted only in refining functions");
 05640      }
 137505641      var option = f.TypeArgs.Count == 0 ? new ResolveTypeOption(f) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 1440905642      foreach (Formal p in f.Formals) {
 342805643        ScopePushAndReport(scope, p, "parameter");
 342805644        ResolveType(p.tok, p.Type, f, option, f.TypeArgs);
 342805645      }
 137505646      if (f.Result != null) {
 05647        ScopePushAndReport(scope, f.Result, "parameter/return");
 05648        ResolveType(f.Result.tok, f.Result.Type, f, option, f.TypeArgs);
 137505649      } else {
 137505650        ResolveType(f.tok, f.ResultType, f, option, f.TypeArgs);
 137505651      }
 137505652      scope.PopMarker();
 137505653    }
 5654
 5655    /// <summary>
 5656    /// This method can be called even if the resolution of "fe" failed; in that case, this method will
 5657    /// not issue any error message.
 5658    /// </summary>
 05659    public void DisallowNonGhostFieldSpecifiers(FrameExpression fe) {
 5660      Contract.Requires(fe != null);
 05661      if (fe.Field != null && !fe.Field.IsGhost) {
 05662        reporter.Error(MessageSource.Resolver, fe.E, "in a ghost context, only ghost fields can be mentioned as modifies
 05663      }
 05664    }
 5665
 5666    /// <summary>
 5667    /// Assumes type parameters have already been pushed
 5668    /// </summary>
 50505669    void ResolveMethodSignature(Method m) {
 5670      Contract.Requires(m != null);
 5671
 50505672      scope.PushMarker();
 50505673      if (m.SignatureIsOmitted) {
 05674        reporter.Error(MessageSource.Resolver, m, "method signature can be omitted only in refining methods");
 05675      }
 50505676      var option = m.TypeArgs.Count == 0 ? new ResolveTypeOption(m) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 5677      // resolve in-parameters
 482405678      foreach (Formal p in m.Ins) {
 110305679        ScopePushAndReport(scope, p, "parameter");
 110305680        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 110305681      }
 5682      // resolve out-parameters
 341705683      foreach (Formal p in m.Outs) {
 63405684        ScopePushAndReport(scope, p, "parameter");
 63405685        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 63405686      }
 50505687      scope.PopMarker();
 50505688    }
 5689
 5690    /// <summary>
 5691    /// Assumes type parameters have already been pushed
 5692    /// </summary>
 05693    void ResolveIteratorSignature(IteratorDecl iter) {
 5694      Contract.Requires(iter != null);
 05695      scope.PushMarker();
 05696      if (iter.SignatureIsOmitted) {
 05697        reporter.Error(MessageSource.Resolver, iter, "iterator signature can be omitted only in refining methods");
 05698      }
 05699      var initiallyNoTypeArguments = iter.TypeArgs.Count == 0;
 05700      var option = initiallyNoTypeArguments ? new ResolveTypeOption(iter) : new ResolveTypeOption(ResolveTypeOptionEnum.
 5701      // resolve the types of the parameters
 05702      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 05703      foreach (var p in iter.Ins) {
 05704        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05705      }
 05706      foreach (var p in iter.Outs) {
 05707        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05708        if (!p.Type.KnownToHaveToAValue(p.IsGhost)) {
 05709          reporter.Error(MessageSource.Resolver, p.tok, "type of yield-parameter must support auto-initialization (got '
 05710        }
 05711      }
 5712      // resolve the types of the added fields (in case some of these types would cause the addition of default type arg
 05713      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05714        foreach (var p in iter.OutsHistoryFields) {
 05715          ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05716        }
 05717      }
 05718      if (iter.TypeArgs.Count != iter.NonNullTypeDecl.TypeArgs.Count) {
 5719        // Apparently, the type resolution automatically added type arguments to the iterator. We'll add these to the
 5720        // corresponding non-null type as well.
 05721        Contract.Assert(initiallyNoTypeArguments);
 05722        Contract.Assert(iter.NonNullTypeDecl.TypeArgs.Count == 0);
 05723        var nnt = iter.NonNullTypeDecl;
 05724        nnt.TypeArgs.AddRange(iter.TypeArgs.ConvertAll(tp => new TypeParameter(tp.RangeToken, tp.NameNode, tp.VarianceSy
 05725        var varUdt = (UserDefinedType)nnt.Var.Type;
 05726        Contract.Assert(varUdt.TypeArgs.Count == 0);
 05727        varUdt.TypeArgs = nnt.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 05728      }
 05729      scope.PopMarker();
 05730    }
 5731
 5732    // Like the ResolveTypeOptionEnum, but iff the case of AllowPrefixExtend, it also
 5733    // contains a pointer to its Parent class, to fill in default type parameters properly.
 5734    public class ResolveTypeOption {
 5735      public readonly ResolveTypeOptionEnum Opt;
 5736      public readonly TypeParameter.ParentType Parent;
 5737      [ContractInvariantMethod]
 05738      void ObjectInvariant() {
 5739        Contract.Invariant((Opt == ResolveTypeOptionEnum.AllowPrefixExtend) == (Parent != null));
 05740      }
 5741
 9437405742      public ResolveTypeOption(ResolveTypeOptionEnum opt) {
 5743        Contract.Requires(opt != ResolveTypeOptionEnum.AllowPrefixExtend);
 4718705744        Parent = null;
 4718705745        Opt = opt;
 4718705746      }
 5747
 226605748      public ResolveTypeOption(TypeParameter.ParentType parent) {
 5749        Contract.Requires(parent != null);
 113305750        Opt = ResolveTypeOptionEnum.AllowPrefixExtend;
 113305751        Parent = parent;
 113305752      }
 5753    }
 5754
 5755    /// <summary>
 5756    /// Returns a resolved type denoting an array type with dimension "dims" and element type "arg".
 5757    /// Callers are expected to provide "arg" as an already resolved type.  (Note, a proxy type is resolved--
 5758    /// only types that contain identifiers stand the possibility of not being resolved.)
 5759    /// </summary>
 05760    Type ResolvedArrayType(IToken tok, int dims, Type arg, ResolutionContext resolutionContext, bool useClassNameType) {
 5761      Contract.Requires(tok != null);
 5762      Contract.Requires(1 <= dims);
 5763      Contract.Requires(arg != null);
 05764      var at = builtIns.ArrayType(tok, dims, new List<Type> { arg }, false, useClassNameType);
 05765      ResolveType(tok, at, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 05766      return at;
 05767    }
 5768
 05769    void FillInDefaultLoopDecreases(LoopStmt loopStmt, Expression guard, List<Expression> theDecreases, ICallable enclos
 5770      Contract.Requires(loopStmt != null);
 5771      Contract.Requires(theDecreases != null);
 5772
 05773      if (theDecreases.Count == 0 && guard != null) {
 05774        loopStmt.InferredDecreases = true;
 05775        Expression prefix = null;
 05776        foreach (Expression guardConjunct in Expression.Conjuncts(guard)) {
 05777          Expression guess = null;
 05778          var neutralValue = Expression.CreateIntLiteral(guardConjunct.tok, -1);
 05779          if (guardConjunct is BinaryExpr bin) {
 05780            switch (bin.ResolvedOp) {
 5781              case BinaryExpr.ResolvedOpcode.Lt:
 5782              case BinaryExpr.ResolvedOpcode.Le:
 5783              case BinaryExpr.ResolvedOpcode.LtChar:
 5784              case BinaryExpr.ResolvedOpcode.LeChar:
 05785                if (bin.E0.Type.IsBigOrdinalType) {
 5786                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05787                  guess = bin.E1;
 05788                } else {
 5789                  // for A < B and A <= B, use the decreases B - A
 05790                  guess = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05791                }
 05792                break;
 5793              case BinaryExpr.ResolvedOpcode.Ge:
 5794              case BinaryExpr.ResolvedOpcode.Gt:
 5795              case BinaryExpr.ResolvedOpcode.GeChar:
 5796              case BinaryExpr.ResolvedOpcode.GtChar:
 05797                if (bin.E0.Type.IsBigOrdinalType) {
 5798                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05799                  guess = bin.E0;
 05800                } else {
 5801                  // for A >= B and A > B, use the decreases A - B
 05802                  guess = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05803                }
 05804                break;
 5805              case BinaryExpr.ResolvedOpcode.ProperSubset:
 5806              case BinaryExpr.ResolvedOpcode.Subset:
 05807                if (bin.E0.Type.AsSetType.Finite) {
 5808                  // for A < B and A <= B, use the decreases |B - A|
 05809                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05810                }
 05811                break;
 5812              case BinaryExpr.ResolvedOpcode.Superset:
 5813              case BinaryExpr.ResolvedOpcode.ProperSuperset:
 05814                if (bin.E0.Type.AsSetType.Finite) {
 5815                  // for A >= B and A > B, use the decreases |A - B|
 05816                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05817                }
 05818                break;
 5819              case BinaryExpr.ResolvedOpcode.ProperMultiSubset:
 5820              case BinaryExpr.ResolvedOpcode.MultiSubset:
 5821                // for A < B and A <= B, use the decreases |B - A|
 05822                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05823                break;
 5824              case BinaryExpr.ResolvedOpcode.MultiSuperset:
 5825              case BinaryExpr.ResolvedOpcode.ProperMultiSuperset:
 5826                // for A >= B and A > B, use the decreases |A - B|
 05827                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05828                break;
 5829              case BinaryExpr.ResolvedOpcode.Prefix:
 5830              case BinaryExpr.ResolvedOpcode.ProperPrefix:
 5831                // for "[] < B" and "[] <= B", use B
 05832                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05833                  guess = bin.E1;
 05834                }
 05835                break;
 5836              case BinaryExpr.ResolvedOpcode.NeqCommon:
 05837                if (bin.E0.Type.IsNumericBased() || bin.E0.Type.IsBitVectorType || bin.E0.Type.IsCharType) {
 5838                  // for A != B where A and B are numeric, use the absolute difference between A and B (that is: if A <=
 05839                  var AminusB = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05840                  var BminusA = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05841                  var test = Expression.CreateAtMost(bin.E0, bin.E1);
 05842                  guess = Expression.CreateITE(test, BminusA, AminusB);
 05843                } else if (bin.E0.Type.IsBigOrdinalType) {
 5844                  // if either of the operands is a literal, pick the other; otherwise, don't make any guess
 05845                  if (Expression.StripParens(bin.E0) is LiteralExpr) {
 05846                    guess = bin.E1;
 05847                  } else if (Expression.StripParens(bin.E1) is LiteralExpr) {
 05848                    guess = bin.E0;
 05849                  }
 05850                }
 05851                break;
 5852              case BinaryExpr.ResolvedOpcode.SetNeq:
 05853                if (bin.E0.Type.AsSetType.Finite) {
 5854                  // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty set
 05855                  if (LiteralExpr.IsEmptySet(bin.E0)) {
 05856                    guess = bin.E1;
 05857                  } else if (LiteralExpr.IsEmptySet(bin.E1)) {
 05858                    guess = bin.E0;
 05859                  } else {
 05860                    var x = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05861                    var y = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05862                    guess = Expression.CreateAdd(x, y);
 05863                  }
 05864                }
 05865                break;
 5866              case BinaryExpr.ResolvedOpcode.MultiSetNeq:
 5867                // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty multiset
 05868                if (LiteralExpr.IsEmptyMultiset(bin.E0)) {
 05869                  guess = bin.E1;
 05870                } else if (LiteralExpr.IsEmptyMultiset(bin.E1)) {
 05871                  guess = bin.E0;
 05872                } else {
 05873                  var x = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05874                  var y = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05875                  guess = Expression.CreateAdd(x, y);
 05876                }
 05877                break;
 5878              case BinaryExpr.ResolvedOpcode.SeqNeq:
 5879                // if either operand is [], then use the other
 05880                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05881                  guess = bin.E1;
 05882                } else if (LiteralExpr.IsEmptySequence(bin.E1)) {
 05883                  guess = bin.E0;
 05884                }
 05885                break;
 5886              default:
 05887                break;
 5888            }
 05889            if (bin.E0.Type.AsSetType != null) {
 05890              neutralValue = new SetDisplayExpr(bin.tok, bin.E0.Type.AsSetType.Finite, new List<Expression>()) {
 05891                Type = bin.E0.Type.NormalizeExpand()
 05892              };
 05893            } else if (bin.E0.Type.AsMultiSetType != null) {
 05894              neutralValue = new MultiSetDisplayExpr(bin.tok, new List<Expression>()) {
 05895                Type = bin.E0.Type.NormalizeExpand()
 05896              };
 05897            } else if (bin.E0.Type.AsSeqType != null) {
 05898              neutralValue = new SeqDisplayExpr(bin.tok, new List<Expression>()) {
 05899                Type = bin.E0.Type.NormalizeExpand()
 05900              };
 05901            } else if (bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 05902              neutralValue = Expression.CreateRealLiteral(bin.tok, BaseTypes.BigDec.FromInt(-1));
 05903            }
 05904          }
 05905          if (guess != null) {
 05906            if (prefix != null) {
 5907              // Make the following guess:  if prefix then guess else neutralValue
 05908              guess = Expression.CreateITE(prefix, guess, neutralValue);
 05909            }
 05910            theDecreases.Add(AutoGeneratedExpression.Create(guess));
 05911          }
 05912          if (prefix == null) {
 05913            prefix = guardConjunct;
 05914          } else {
 05915            prefix = Expression.CreateAnd(prefix, guardConjunct);
 05916          }
 05917        }
 05918      }
 05919      if (enclosingMethod is IteratorDecl) {
 05920        var iter = (IteratorDecl)enclosingMethod;
 05921        var ie = new IdentifierExpr(loopStmt.Tok, iter.YieldCountVariable.Name);
 05922        ie.Var = iter.YieldCountVariable;  // resolve here
 05923        ie.Type = iter.YieldCountVariable.Type;  // resolve here
 05924        theDecreases.Insert(0, AutoGeneratedExpression.Create(ie));
 05925        loopStmt.InferredDecreases = true;
 05926      }
 05927      if (loopStmt.InferredDecreases && theDecreases.Count != 0) {
 05928        string s = "decreases " + Util.Comma(theDecreases, expr => Printer.ExprToString(Options, expr));
 05929        reporter.Info(MessageSource.Resolver, loopStmt.Tok, s);
 05930      }
 05931    }
 5932
 05933    public Expression VarDotMethod(IToken tok, string varname, string methodname) {
 05934      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), methodname, null), new Li
 05935    }
 5936
 05937    public Expression makeTemp(String prefix, AssignOrReturnStmt s, ResolutionContext resolutionContext, Expression ex) 
 05938      var temp = FreshTempVarName(prefix, resolutionContext.CodeContext);
 05939      var locvar = new LocalVariable(s.RangeToken, temp, ex.Type, false);
 05940      var id = new IdentifierExpr(s.Tok, temp);
 05941      var idlist = new List<Expression>() { id };
 05942      var lhss = new List<LocalVariable>() { locvar };
 05943      var rhss = new List<AssignmentRhs>() { new ExprRhs(ex) };
 05944      var up = new UpdateStmt(s.RangeToken, idlist, rhss);
 05945      s.ResolvedStatements.Add(new VarDeclStmt(s.RangeToken, lhss, up));
 05946      return id;
 05947    }
 5948
 05949    public void EnsureSupportsErrorHandling(IToken tok, Type tp, bool expectExtract, bool hasKeywordToken) {
 5950      // The "method not found" errors which will be generated here were already reported while
 5951      // resolving the statement, so we don't want them to reappear and redirect them into a sink.
 05952      var origReporter = this.reporter;
 05953      this.reporter = new ErrorReporterSink(Options, origReporter.OuterModule);
 5954
 05955      var isFailure = ResolveMember(tok, tp, "IsFailure", out _);
 05956      var propagateFailure = ResolveMember(tok, tp, "PropagateFailure", out _);
 05957      var extract = ResolveMember(tok, tp, "Extract", out _);
 5958
 05959      if (hasKeywordToken) {
 05960        if (isFailure == null || (extract != null) != expectExtract) {
 5961          // more details regarding which methods are missing have already been reported by regular resolution
 05962          origReporter.Error(MessageSource.Resolver, tok,
 05963            "The right-hand side of ':-', which is of type '{0}', with a keyword token must have function{1}", tp,
 05964            expectExtract
 05965              ? "s 'IsFailure()' and 'Extract()'"
 05966              : " 'IsFailure()', but not 'Extract()'");
 05967        }
 05968      } else {
 05969        if (isFailure == null || propagateFailure == null || (extract != null) != expectExtract) {
 5970          // more details regarding which methods are missing have already been reported by regular resolution
 05971          origReporter.Error(MessageSource.Resolver, tok,
 05972            "The right-hand side of ':-', which is of type '{0}', must have function{1}", tp,
 05973            expectExtract
 05974              ? "s 'IsFailure()', 'PropagateFailure()', and 'Extract()'"
 05975              : "s 'IsFailure()' and 'PropagateFailure()', but not 'Extract()'");
 05976        }
 05977      }
 5978
 05979      void checkIsFunction([CanBeNull] MemberDecl memberDecl, bool allowMethod) {
 05980        if (memberDecl == null || memberDecl is Function) {
 5981          // fine
 05982        } else if (allowMethod && memberDecl is Method) {
 5983          // give a deprecation warning, so we will remove this language feature around the Dafny 4 time frame
 05984          origReporter.Deprecated(MessageSource.Resolver, ErrorRegistry.NoneId, tok,
 05985            $"Support for member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) being a method 
 05986            " declare it to be a function instead");
 05987        } else {
 5988          // not allowed
 05989          origReporter.Error(MessageSource.Resolver, tok,
 05990            $"Member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) is expected to be a functio
 05991        }
 05992      }
 5993
 05994      checkIsFunction(isFailure, false);
 05995      if (!hasKeywordToken) {
 05996        checkIsFunction(propagateFailure, true);
 05997      }
 05998      if (expectExtract) {
 05999        checkIsFunction(extract, true);
 06000      }
 6001
 06002      this.reporter = origReporter;
 06003    }
 6004
 6005    /// <summary>
 6006    /// Check that "stmt" is a valid statment for the body of an assert-by, forall,
 6007    /// or calc-hint statement. In particular, check that the local variables assigned in
 6008    /// the bodies of these statements are declared in the statements, not in some enclosing
 6009    /// context.
 6010    /// </summary>
 06011    public void CheckLocalityUpdates(Statement stmt, ISet<LocalVariable> localsAllowedInUpdates, string where) {
 6012      Contract.Requires(stmt != null);
 6013      Contract.Requires(localsAllowedInUpdates != null);
 6014      Contract.Requires(where != null);
 6015
 06016      if (stmt is AssertStmt || stmt is ForallStmt || stmt is CalcStmt || stmt is ModifyStmt) {
 6017        // don't recurse, since CheckHintRestrictions will be called on that assert-by separately
 06018        return;
 06019      } else if (stmt is AssignSuchThatStmt) {
 06020        var s = (AssignSuchThatStmt)stmt;
 06021        foreach (var lhs in s.Lhss) {
 06022          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06023        }
 06024      } else if (stmt is AssignStmt) {
 06025        var s = (AssignStmt)stmt;
 06026        CheckLocalityUpdatesLhs(s.Lhs, localsAllowedInUpdates, @where);
 06027      } else if (stmt is CallStmt) {
 06028        var s = (CallStmt)stmt;
 06029        foreach (var lhs in s.Lhs) {
 06030          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06031        }
 06032      } else if (stmt is VarDeclStmt) {
 06033        var s = (VarDeclStmt)stmt;
 06034        s.Locals.Iter(local => localsAllowedInUpdates.Add(local));
 06035      } else if (stmt is ModifyStmt) {
 6036        // no further complaints (note, ghost interests have already checked for 'modify' statements)
 06037      } else if (stmt is BlockStmt) {
 06038        localsAllowedInUpdates = new HashSet<LocalVariable>(localsAllowedInUpdates);
 6039        // use this new set for the recursive calls
 06040      }
 6041
 06042      foreach (var ss in stmt.SubStatements) {
 06043        CheckLocalityUpdates(ss, localsAllowedInUpdates, where);
 06044      }
 06045    }
 6046
 06047    void CheckLocalityUpdatesLhs(Expression lhs, ISet<LocalVariable> localsAllowedInUpdates, string @where) {
 6048      Contract.Requires(lhs != null);
 6049      Contract.Requires(localsAllowedInUpdates != null);
 6050      Contract.Requires(where != null);
 6051
 06052      lhs = lhs.Resolved;
 06053      if (lhs is IdentifierExpr idExpr && !localsAllowedInUpdates.Contains(idExpr.Var)) {
 06054        reporter.Error(MessageSource.Resolver, lhs.tok, "{0} is not allowed to update a variable it doesn't declare", wh
 06055      }
 06056    }
 6057
 6058    class LazyString_OnTypeEquals {
 6059      Type t0;
 6060      Type t1;
 6061      string s;
 06062      public LazyString_OnTypeEquals(Type t0, Type t1, string s) {
 6063        Contract.Requires(t0 != null);
 6064        Contract.Requires(t1 != null);
 6065        Contract.Requires(s != null);
 06066        this.t0 = t0;
 06067        this.t1 = t1;
 06068        this.s = s;
 06069      }
 06070      public override string ToString() {
 06071        return t0.Equals(t1) ? s : "";
 06072      }
 6073    }
 6074
 06075    void FindAllMembers(ClassDecl cl, string memberName, ISet<MemberDecl> foundSoFar) {
 6076      Contract.Requires(cl != null);
 6077      Contract.Requires(memberName != null);
 6078      Contract.Requires(foundSoFar != null);
 6079      MemberDecl member;
 06080      if (classMembers[cl].TryGetValue(memberName, out member)) {
 06081        foundSoFar.Add(member);
 06082      }
 06083      cl.ParentTraitHeads.ForEach(trait => FindAllMembers(trait, memberName, foundSoFar));
 06084    }
 6085
 6086    // TODO move
 8306087    public static UserDefinedType GetThisType(IToken tok, TopLevelDeclWithMembers cl) {
 6088      Contract.Requires(tok != null);
 6089      Contract.Requires(cl != null);
 6090      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6091
 16606092      if (cl is ClassDecl cls && cls.NonNullTypeDecl != null) {
 8306093        return UserDefinedType.FromTopLevelDecl(tok, cls.NonNullTypeDecl, cls.TypeArgs);
 06094      } else {
 06095        return UserDefinedType.FromTopLevelDecl(tok, cl, cl.TypeArgs);
 6096      }
 8306097    }
 6098
 6099    // TODO move
 06100    public static UserDefinedType GetReceiverType(IToken tok, MemberDecl member) {
 6101      Contract.Requires(tok != null);
 6102      Contract.Requires(member != null);
 6103      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6104
 06105      return GetThisType(tok, (TopLevelDeclWithMembers)member.EnclosingClass);
 06106    }
 6107
 06108    Label/*?*/ ResolveDominatingLabelInExpr(IToken tok, string/*?*/ labelName, string expressionDescription, ResolutionC
 6109      Contract.Requires(tok != null);
 6110      Contract.Requires(expressionDescription != null);
 6111      Contract.Requires(resolutionContext != null);
 6112
 06113      Label label = null;
 06114      if (!resolutionContext.IsTwoState) {
 06115        reporter.Error(MessageSource.Resolver, tok, $"{expressionDescription} expressions are not allowed in this contex
 06116      } else if (labelName != null) {
 06117        label = DominatingStatementLabels.Find(labelName);
 06118        if (label == null) {
 06119          reporter.Error(MessageSource.Resolver, tok, $"no label '{labelName}' in scope at this time");
 06120        }
 06121      }
 06122      return label;
 06123    }
 6124
 06125    private Expression VarDotFunction(IToken tok, string varname, string functionname) {
 06126      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), functionname, null), new 
 06127    }
 6128
 6129    // TODO search for occurrences of "new LetExpr" which could benefit from this helper
 06130    private LetExpr LetPatIn(IToken tok, CasePattern<BoundVar> lhs, Expression rhs, Expression body) {
 06131      return new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { rhs }, body, true);
 06132    }
 6133
 06134    private LetExpr LetVarIn(IToken tok, string name, Type tp, Expression rhs, Expression body) {
 06135      var lhs = new CasePattern<BoundVar>(tok, new BoundVar(tok, name, tp));
 06136      return LetPatIn(tok, lhs, rhs, body);
 06137    }
 6138
 6139    /// <summary>
 6140    ///  If expr.Lhs != null: Desugars "var x: T :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6141    ///  If expr.Lhs == null: Desugars "         :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6142    /// </summary>
 06143    public void ResolveLetOrFailExpr(LetOrFailExpr expr, ResolutionContext resolutionContext) {
 06144      var temp = FreshTempVarName("valueOrError", resolutionContext.CodeContext);
 06145      var tempType = new InferredTypeProxy();
 6146      // "var temp := E;"
 06147      expr.ResolvedExpression = LetVarIn(expr.tok, temp, tempType, expr.Rhs,
 06148        // "if temp.IsFailure()"
 06149        new ITEExpr(expr.tok, false, VarDotFunction(expr.tok, temp, "IsFailure"),
 06150          // "then temp.PropagateFailure()"
 06151          VarDotFunction(expr.tok, temp, "PropagateFailure"),
 06152          // "else"
 06153          expr.Lhs == null
 06154            // "F"
 06155            ? expr.Body
 06156            // "var x: T := temp.Extract(); F"
 06157            : LetPatIn(expr.tok, expr.Lhs, VarDotFunction(expr.tok, temp, "Extract"), expr.Body)));
 6158
 06159      ResolveExpression(expr.ResolvedExpression, resolutionContext);
 06160      expr.Type = expr.ResolvedExpression.Type;
 06161      bool expectExtract = (expr.Lhs != null);
 06162      EnsureSupportsErrorHandling(expr.tok, PartiallyResolveTypeForMemberSelection(expr.tok, tempType), expectExtract, f
 06163    }
 6164
 100006165    public static Type SelectAppropriateArrowTypeForFunction(Function function, Dictionary<TypeParameter, Type> subst, B
 100006166      return SelectAppropriateArrowType(function.tok,
 253706167        function.Formals.ConvertAll(formal => formal.Type.Subst(subst)),
 100006168        function.ResultType.Subst(subst),
 100006169        function.Reads.Count != 0, function.Req.Count != 0,
 100006170        builtIns);
 100006171    }
 6172
 153306173    public static Type SelectAppropriateArrowType(IToken tok, List<Type> typeArgs, Type resultType, bool hasReads, bool 
 6174      Contract.Requires(tok != null);
 6175      Contract.Requires(typeArgs != null);
 6176      Contract.Requires(resultType != null);
 153306177      var arity = typeArgs.Count;
 153306178      var typeArgsAndResult = Util.Snoc(typeArgs, resultType);
 153306179      if (hasReads) {
 6180        // any arrow
 06181        return new ArrowType(tok, builtIns.ArrowTypeDecls[arity], typeArgsAndResult);
 153306182      } else if (hasReq) {
 6183        // partial arrow
 06184        return new UserDefinedType(tok, ArrowType.PartialArrowTypeName(arity), builtIns.PartialArrowTypeDecls[arity], ty
 153306185      } else {
 6186        // total arrow
 153306187        return new UserDefinedType(tok, ArrowType.TotalArrowTypeName(arity), builtIns.TotalArrowTypeDecls[arity], typeAr
 6188      }
 153306189    }
 6190
 6191    /// <summary>
 6192    /// Adds appropriate type constraints that says "expr" evaluates to an integer or (if "allowBitVector" is true) a
 6193    /// a bitvector.  The "errFormat" string can contain a "{0}", referring to the name of the type of "expr".
 6194    /// </summary>
 12606195    void ConstrainToIntegerType(Expression expr, bool allowBitVector, string errFormat) {
 6196      Contract.Requires(expr != null);
 6197      Contract.Requires(errFormat != null);
 12606198      var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, errFormat, expr.Type);
 12606199      ConstrainToIntegerType(expr.tok, expr.Type, allowBitVector, err);
 12606200    }
 6201
 6202    /// <summary>
 6203    /// Resolves a NestedMatchExpr by
 6204    /// 1 - checking that all of its patterns are linear
 6205    /// 2 - desugaring it into a decision tree of MatchExpr and ITEEXpr (for constant matching)
 6206    /// 3 - resolving the generated (sub)expression.
 6207    /// </summary>
 06208    void ResolveNestedMatchExpr(NestedMatchExpr nestedMatchExpr, ResolutionContext resolutionContext) {
 6209      Contract.Requires(nestedMatchExpr != null);
 6210      Contract.Requires(resolutionContext != null);
 6211
 06212      nestedMatchExpr.Resolve(this, resolutionContext);
 06213    }
 6214
 6215    void ResolveCasePattern<VT>(CasePattern<VT> pat, Type sourceType, ResolutionContext resolutionContext)
 383906216      where VT : class, IVariable {
 6217      Contract.Requires(pat != null);
 6218      Contract.Requires(sourceType != null);
 6219      Contract.Requires(resolutionContext != null);
 6220
 383906221      DatatypeDecl dtd = null;
 383906222      UserDefinedType udt = null;
 421406223      if (sourceType.IsDatatype) {
 37506224        udt = (UserDefinedType)sourceType.NormalizeExpand();
 37506225        dtd = (DatatypeDecl)udt.ResolvedClass;
 37506226      }
 6227      // Find the constructor in the given datatype
 6228      // If what was parsed was just an identifier, we will interpret it as a datatype constructor, if possible
 383906229      DatatypeCtor ctor = null;
 421406230      if (dtd != null) {
 75006231        if (pat.Var == null || (pat.Var != null && pat.Var.Type is TypeProxy)) {
 37506232          if (dtd.ConstructorsByName.TryGetValue(pat.Id, out ctor)) {
 06233            if (pat.Arguments == null) {
 06234              if (ctor.Formals.Count != 0) {
 6235                // Leave this as a variable
 06236              } else {
 6237                // Convert to a constructor
 06238                pat.MakeAConstructor();
 06239                pat.Ctor = ctor;
 06240                pat.Var = default(VT);
 06241              }
 06242            } else {
 06243              pat.Ctor = ctor;
 06244              pat.Var = default(VT);
 06245            }
 06246          }
 37506247        }
 37506248      }
 6249
 767806250      if (pat.Var != null) {
 6251        // this is a simple resolution
 383906252        var v = pat.Var;
 383906253        if (resolutionContext.IsGhost) {
 06254          v.MakeGhost();
 06255        }
 383906256        ResolveType(v.Tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 6257        // Note, the following type constraint checks that the RHS type can be assigned to the new variable on the left.
 6258        // does not check that the entire RHS can be assigned to something of the type of the pattern on the left.  For 
 6259        // a type declared as "datatype Atom<T> = MakeAtom(T)", where T is a non-variant type argument.  Suppose the RHS
 6260        // and that the LHS is the pattern MakeAtom(x: int).  This is okay, despite the fact that Atom<nat> is not assig
 6261        // The reason is that the purpose of the pattern on the left is really just to provide a skeleton to introduce b
 383906262        EagerAddAssignableConstraint(v.Tok, v.Type, sourceType, "type of corresponding source/RHS ({1}) does not match t
 383906263        pat.AssembleExpr(null);
 383906264        return;
 6265      }
 06266      if (dtd == null) {
 6267        // look up the name of the pattern's constructor
 6268        Tuple<DatatypeCtor, bool> pair;
 06269        if (moduleInfo.Ctors.TryGetValue(pat.Id, out pair) && !pair.Item2) {
 06270          ctor = pair.Item1;
 06271          pat.Ctor = ctor;
 06272          dtd = ctor.EnclosingDatatype;
 06273          var typeArgs = new List<Type>();
 06274          foreach (var xt in dtd.TypeArgs) {
 06275            typeArgs.Add(new InferredTypeProxy());
 06276          }
 06277          udt = new UserDefinedType(pat.tok, dtd.Name, dtd, typeArgs);
 06278          ConstrainSubtypeRelation(udt, sourceType, pat.tok, "type of RHS ({0}) does not match type of bound variable '{
 06279        }
 06280      }
 06281      if (dtd == null && ctor == null) {
 06282        reporter.Error(MessageSource.Resolver, pat.tok, "to use a pattern, the type of the source/RHS expression must be
 06283      } else if (ctor == null) {
 06284        reporter.Error(MessageSource.Resolver, pat.tok, "constructor {0} does not exist in datatype {1}", pat.Id, dtd.Na
 06285      } else {
 06286        if (pat.Arguments == null) {
 06287          if (ctor.Formals.Count == 0) {
 6288            // The Id matches a constructor of the correct type and 0 arguments,
 6289            // so make it a nullary constructor, not a variable
 06290            pat.MakeAConstructor();
 06291          }
 06292        } else {
 06293          if (ctor.Formals.Count != pat.Arguments.Count) {
 06294            reporter.Error(MessageSource.Resolver, pat.tok, "pattern for constructor {0} has wrong number of formals (fo
 06295          }
 06296        }
 6297        // build the type-parameter substitution map for this use of the datatype
 06298        Contract.Assert(dtd.TypeArgs.Count == udt.TypeArgs.Count);  // follows from the type previously having been succ
 06299        var subst = TypeParameter.SubstitutionMap(dtd.TypeArgs, udt.TypeArgs);
 6300        // recursively call ResolveCasePattern on each of the arguments
 06301        var j = 0;
 06302        if (pat.Arguments != null) {
 06303          foreach (var arg in pat.Arguments) {
 06304            if (j < ctor.Formals.Count) {
 06305              var formal = ctor.Formals[j];
 06306              Type st = formal.Type.Subst(subst);
 06307              ResolveCasePattern(arg, st, resolutionContext.WithGhost(resolutionContext.IsGhost || formal.IsGhost));
 06308            }
 06309            j++;
 06310          }
 06311        }
 06312        if (j == ctor.Formals.Count) {
 06313          pat.AssembleExpr(udt.TypeArgs);
 06314        }
 06315      }
 383906316    }
 6317
 4156318    private List<DefaultValueExpression> allDefaultValueExpressions = new List<DefaultValueExpression>();
 6319
 6320    /// <summary>
 6321    /// This method is called at the tail end of Pass1 of the Resolver.
 6322    /// </summary>
 12456323    void FillInDefaultValueExpressions() {
 12456324      var visited = new Dictionary<DefaultValueExpression, WorkProgress>();
 37356325      foreach (var e in allDefaultValueExpressions) {
 06326        FillInDefaultValueExpression(e, visited);
 06327      }
 12456328      allDefaultValueExpressions.Clear();
 12456329    }
 6330
 6331    enum WorkProgress { BeingVisited, Done }
 6332
 06333    void FillInDefaultValueExpression(DefaultValueExpression expr, Dictionary<DefaultValueExpression, WorkProgress> visi
 6334      Contract.Requires(expr != null);
 6335      Contract.Requires(visited != null);
 6336      Contract.Ensures(expr.ResolvedExpression != null);
 6337
 06338      if (visited.TryGetValue(expr, out var p)) {
 06339        if (p == WorkProgress.Done) {
 06340          Contract.Assert(expr.ResolvedExpression != null);
 06341        } else {
 6342          // there is a cycle
 06343          reporter.Error(MessageSource.Resolver, expr, "default-valued expressions are cyclicly dependent; this is not a
 6344          // nevertheless, to avoid any issues in the resolver, fill in the .ResolvedExpression field with something
 06345          expr.ResolvedExpression = Expression.CreateBoolLiteral(expr.tok, false);
 06346        }
 06347        return;
 6348      }
 06349      Contract.Assert(expr.ResolvedExpression == null);
 6350
 06351      visited.Add(expr, WorkProgress.BeingVisited);
 06352      var s = new DefaultValueSubstituter(this, visited, expr.Receiver, expr.SubstMap, expr.TypeMap);
 06353      expr.ResolvedExpression = s.Substitute(expr.Formal.DefaultValue);
 06354      visited[expr] = WorkProgress.Done;
 06355    }
 6356
 6357    class DefaultValueSubstituter : Substituter {
 6358      private readonly Resolver resolver;
 6359      private readonly Dictionary<DefaultValueExpression, WorkProgress> visited;
 6360      public DefaultValueSubstituter(Resolver resolver, Dictionary<DefaultValueExpression, WorkProgress> visited,
 6361        Expression /*?*/ receiverReplacement, Dictionary<IVariable, Expression> substMap, Dictionary<TypeParameter, Type
 06362        : base(receiverReplacement, substMap, typeMap) {
 6363        Contract.Requires(resolver != null);
 6364        Contract.Requires(visited != null);
 06365        this.resolver = resolver;
 06366        this.visited = visited;
 06367      }
 6368
 06369      public override Expression Substitute(Expression expr) {
 06370        if (expr is DefaultValueExpression dve) {
 06371          resolver.FillInDefaultValueExpression(dve, visited);
 06372          Contract.Assert(dve.ResolvedExpression != null); // postcondition of FillInDefaultValueExpression
 06373        }
 06374        return base.Substitute(expr);
 06375      }
 6376    }
 6377
 6378    public Dictionary<TypeParameter, Type> BuildTypeArgumentSubstitute(Dictionary<TypeParameter, Type> typeArgumentSubst
 376206379      Type/*?*/ receiverTypeBound = null) {
 6380      Contract.Requires(typeArgumentSubstitutions != null);
 6381
 376206382      var subst = new Dictionary<TypeParameter, Type>();
 2076906383      foreach (var entry in typeArgumentSubstitutions) {
 316106384        subst.Add(entry.Key, entry.Value);
 316106385      }
 6386
 376206387      if (SelfTypeSubstitution != null) {
 06388        foreach (var entry in SelfTypeSubstitution) {
 06389          subst.Add(entry.Key, entry.Value);
 06390        }
 06391      }
 6392
 678706393      if (receiverTypeBound != null) {
 302506394        subst = AddParentTypeParameterSubstitutions(subst, receiverTypeBound);
 302506395      }
 6396
 376206397      return subst;
 376206398    }
 6399
 302506400    public static Dictionary<TypeParameter, Type> AddParentTypeParameterSubstitutions(Dictionary<TypeParameter, Type> su
 6401      TopLevelDeclWithMembers cl;
 302506402      var udt = receiverType?.AsNonNullRefType;
 302506403      if (udt != null) {
 06404        cl = (TopLevelDeclWithMembers)((NonNullTypeDecl)udt.ResolvedClass).ViewAsClass;
 302506405      } else {
 302506406        udt = receiverType.NormalizeExpand() as UserDefinedType;
 302506407        cl = udt?.ResolvedClass as TopLevelDeclWithMembers;
 302506408      }
 605006409      if (cl != null) {
 907506410        foreach (var entry in cl.ParentFormalTypeParametersToActuals) {
 06411          var v = entry.Value.Subst(subst);
 06412          subst.Add(entry.Key, v);
 06413        }
 302506414      }
 6415
 302506416      return subst;
 302506417    }
 6418
 1042296419    public static string GhostPrefix(bool isGhost) {
 1042296420      return isGhost ? "ghost " : "";
 1042296421    }
 6422
 06423    private static ModuleSignature GetSignatureExt(ModuleSignature sig, bool useCompileSignatures) {
 6424      Contract.Requires(sig != null);
 6425      Contract.Ensures(Contract.Result<ModuleSignature>() != null);
 06426      if (useCompileSignatures) {
 06427        while (sig.CompileSignature != null) {
 06428          sig = sig.CompileSignature;
 06429        }
 06430      }
 06431      return sig;
 06432    }
 6433
 06434    private ModuleSignature GetSignature(ModuleSignature sig) {
 06435      return GetSignatureExt(sig, useCompileSignatures);
 06436    }
 6437
 4156438    public static Expression GetImpliedTypeConstraint(IVariable bv, Type ty) {
 4156439      return GetImpliedTypeConstraint(Expression.CreateIdentExpr(bv), ty);
 4156440    }
 6441
 24906442    public static Expression GetImpliedTypeConstraint(Expression e, Type ty) {
 6443      Contract.Requires(e != null);
 6444      Contract.Requires(ty != null);
 24906445      ty = ty.NormalizeExpandKeepConstraints();
 24906446      var udt = ty as UserDefinedType;
 37356447      if (udt != null) {
 12456448        if (udt.ResolvedClass is NewtypeDecl) {
 06449          var dd = (NewtypeDecl)udt.ResolvedClass;
 06450          var c = GetImpliedTypeConstraint(e, dd.BaseType);
 06451          if (dd.Var != null) {
 06452            Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 06453            substMap.Add(dd.Var, e);
 06454            Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 06455            c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 06456          }
 06457          return c;
 24906458        } else if (udt.ResolvedClass is SubsetTypeDecl) {
 12456459          var dd = (SubsetTypeDecl)udt.ResolvedClass;
 12456460          var c = GetImpliedTypeConstraint(e, dd.RhsWithArgument(udt.TypeArgs));
 12456461          Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 12456462          substMap.Add(dd.Var, e);
 12456463          Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 12456464          c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 12456465          return c;
 6466        }
 06467      }
 12456468      return Expression.CreateBoolLiteral(e.tok, true);
 24906469    }
 6470
 6471    /// <summary>
 6472    /// Returns the set of free variables in "expr".
 6473    /// Requires "expr" to be successfully resolved.
 6474    /// Ensures that the set returned has no aliases.
 6475    /// </summary>
 06476    static ISet<IVariable> FreeVariables(Expression expr) {
 6477      Contract.Requires(expr != null);
 6478      Contract.Ensures(expr.Type != null);
 6479
 06480      if (expr is IdentifierExpr) {
 06481        var e = (IdentifierExpr)expr;
 06482        return new HashSet<IVariable>() { e.Var };
 6483
 06484      } else if (expr is QuantifierExpr) {
 06485        var e = (QuantifierExpr)expr;
 06486        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 6487
 06488        var s = FreeVariables(e.LogicalBody());
 06489        foreach (var bv in e.BoundVars) {
 06490          s.Remove(bv);
 06491        }
 06492        return s;
 06493      } else if (expr is NestedMatchExpr) {
 06494        var e = (NestedMatchExpr)expr;
 06495        var s = FreeVariables(e.Source);
 06496        foreach (NestedMatchCaseExpr mc in e.Cases) {
 06497          var t = FreeVariables(mc.Body);
 06498          foreach (var bv in mc.Pat.Children.OfType<IdPattern>()) {
 06499            if (bv.BoundVar != null) {
 06500              t.Remove(bv.BoundVar);
 06501            }
 06502          }
 06503          s.UnionWith(t);
 06504        }
 06505        return s;
 06506      } else if (expr is MatchExpr) {
 06507        var e = (MatchExpr)expr;
 06508        var s = FreeVariables(e.Source);
 06509        foreach (MatchCaseExpr mc in e.Cases) {
 06510          var t = FreeVariables(mc.Body);
 06511          foreach (var bv in mc.Arguments) {
 06512            t.Remove(bv);
 06513          }
 06514          s.UnionWith(t);
 06515        }
 06516        return s;
 6517
 06518      } else if (expr is LambdaExpr) {
 06519        var e = (LambdaExpr)expr;
 06520        var s = FreeVariables(e.Term);
 06521        if (e.Range != null) {
 06522          s.UnionWith(FreeVariables(e.Range));
 06523        }
 06524        foreach (var fe in e.Reads) {
 06525          s.UnionWith(FreeVariables(fe.E));
 06526        }
 06527        foreach (var bv in e.BoundVars) {
 06528          s.Remove(bv);
 06529        }
 06530        return s;
 6531
 06532      } else {
 06533        ISet<IVariable> s = null;
 06534        foreach (var e in expr.SubExpressions) {
 06535          var t = FreeVariables(e);
 06536          if (s == null) {
 06537            s = t;
 06538          } else {
 06539            s.UnionWith(t);
 06540          }
 06541        }
 06542        return s == null ? new HashSet<IVariable>() : s;
 6543      }
 06544    }
 6545
 6546    /// <summary>
 6547    /// An error message for the type constraint for between a sequence select expression's actual and expected types.
 6548    /// If resolution successfully determines the sequences' element types, then this derived class mentions those
 6549    /// element types as clarifying context to the user.
 6550    /// </summary>
 6551    private class SeqSelectOneErrorMsg : TypeConstraint.ErrorMsgWithToken {
 4156552      private static readonly string BASE_MESSAGE_FORMAT = "sequence has type {0} which is incompatible with expected ty
 4156553      private static readonly string ELEMENT_DETAIL_MESSAGE_FORMAT = " (element type {0} is incompatible with {1})";
 6554
 6555      private readonly Type exprSeqType;
 6556      private readonly Type expectedSeqType;
 6557
 6558      public override string Msg {
 06559        get {
 6560          // Resolution might resolve exprSeqType/expectedSeqType to not be sequences at all.
 6561          // In that case, it isn't possible to get the corresponding element types.
 06562          var rawExprElementType = exprSeqType.AsSeqType?.Arg;
 06563          var rawExpectedElementType = expectedSeqType.AsSeqType?.Arg;
 06564          if (rawExprElementType == null || rawExpectedElementType == null) {
 06565            return base.Msg;
 6566          }
 6567
 06568          var elementTypes = RemoveAmbiguity(new object[] { rawExprElementType, rawExpectedElementType });
 06569          Contract.Assert(elementTypes.Length == 2);
 06570          var exprElementType = elementTypes[0].ToString();
 06571          var expectedElementType = elementTypes[1].ToString();
 6572
 06573          string detail = string.Format(ELEMENT_DETAIL_MESSAGE_FORMAT, exprElementType, expectedElementType);
 06574          return base.Msg + detail;
 06575        }
 6576      }
 6577
 6578      public SeqSelectOneErrorMsg(IToken tok, Type exprSeqType, Type expectedSeqType)
 25806579        : base(tok, BASE_MESSAGE_FORMAT, exprSeqType, expectedSeqType) {
 6580        Contract.Requires(exprSeqType != null);
 6581        Contract.Requires(expectedSeqType != null);
 12906582        this.exprSeqType = exprSeqType;
 12906583        this.expectedSeqType = expectedSeqType;
 12906584      }
 6585    }
 6586
 6587    /// <summary>
 6588    /// Note: this method is allowed to be called even if "type" does not make sense for "op", as might be the case if
 6589    /// resolution of the binary expression failed.  If so, an arbitrary resolved opcode is returned.
 6590    /// Usually, the type of the right-hand operand is used to determine the resolved operator (hence, the shorter
 6591    /// name "operandType" instead of, say, "rightOperandType").
 6592    /// </summary>
 655306593    public static BinaryExpr.ResolvedOpcode ResolveOp(BinaryExpr.Opcode op, Type leftOperandType, Type operandType) {
 6594      Contract.Requires(leftOperandType != null);
 6595      Contract.Requires(operandType != null);
 655306596      leftOperandType = leftOperandType.NormalizeExpand();
 655306597      operandType = operandType.NormalizeExpand();
 655306598      switch (op) {
 5506599        case BinaryExpr.Opcode.Iff: return BinaryExpr.ResolvedOpcode.Iff;
 3406600        case BinaryExpr.Opcode.Imp: return BinaryExpr.ResolvedOpcode.Imp;
 5306601        case BinaryExpr.Opcode.Exp: return BinaryExpr.ResolvedOpcode.Imp;
 145706602        case BinaryExpr.Opcode.And: return BinaryExpr.ResolvedOpcode.And;
 2606603        case BinaryExpr.Opcode.Or: return BinaryExpr.ResolvedOpcode.Or;
 6604        case BinaryExpr.Opcode.Eq:
 24906605          if (operandType is SetType) {
 4006606            return BinaryExpr.ResolvedOpcode.SetEq;
 19906607          } else if (operandType is MultiSetType) {
 3006608            return BinaryExpr.ResolvedOpcode.MultiSetEq;
 13906609          } else if (operandType is SeqType) {
 06610            return BinaryExpr.ResolvedOpcode.SeqEq;
 13906611          } else if (operandType is MapType) {
 06612            return BinaryExpr.ResolvedOpcode.MapEq;
 13906613          } else {
 13906614            return BinaryExpr.ResolvedOpcode.EqCommon;
 6615          }
 6616        case BinaryExpr.Opcode.Neq:
 8306617          if (operandType is SetType) {
 06618            return BinaryExpr.ResolvedOpcode.SetNeq;
 8306619          } else if (operandType is MultiSetType) {
 06620            return BinaryExpr.ResolvedOpcode.MultiSetNeq;
 8306621          } else if (operandType is SeqType) {
 06622            return BinaryExpr.ResolvedOpcode.SeqNeq;
 8306623          } else if (operandType is MapType) {
 06624            return BinaryExpr.ResolvedOpcode.MapNeq;
 8306625          } else {
 8306626            return BinaryExpr.ResolvedOpcode.NeqCommon;
 6627          }
 6628        case BinaryExpr.Opcode.Disjoint:
 21106629          if (operandType is MultiSetType) {
 7306630            return BinaryExpr.ResolvedOpcode.MultiSetDisjoint;
 6506631          } else {
 6506632            return BinaryExpr.ResolvedOpcode.Disjoint;
 6633          }
 6634        case BinaryExpr.Opcode.Lt:
 34306635          if (operandType.IsIndDatatype) {
 06636            return BinaryExpr.ResolvedOpcode.RankLt;
 35606637          } else if (operandType is SetType) {
 1306638            return BinaryExpr.ResolvedOpcode.ProperSubset;
 33906639          } else if (operandType is MultiSetType) {
 906640            return BinaryExpr.ResolvedOpcode.ProperMultiSubset;
 32106641          } else if (operandType is SeqType) {
 06642            return BinaryExpr.ResolvedOpcode.ProperPrefix;
 34106643          } else if (operandType is CharType) {
 2006644            return BinaryExpr.ResolvedOpcode.LtChar;
 30106645          } else {
 30106646            return BinaryExpr.ResolvedOpcode.Lt;
 6647          }
 6648        case BinaryExpr.Opcode.Le:
 188706649          if (operandType is SetType) {
 1206650            return BinaryExpr.ResolvedOpcode.Subset;
 187606651          } else if (operandType is MultiSetType) {
 1306652            return BinaryExpr.ResolvedOpcode.MultiSubset;
 185006653          } else if (operandType is SeqType) {
 06654            return BinaryExpr.ResolvedOpcode.Prefix;
 186006655          } else if (operandType is CharType) {
 1006656            return BinaryExpr.ResolvedOpcode.LeChar;
 184006657          } else {
 184006658            return BinaryExpr.ResolvedOpcode.Le;
 6659          }
 6660        case BinaryExpr.Opcode.LeftShift:
 06661          return BinaryExpr.ResolvedOpcode.LeftShift;
 6662        case BinaryExpr.Opcode.RightShift:
 06663          return BinaryExpr.ResolvedOpcode.RightShift;
 6664        case BinaryExpr.Opcode.Add:
 166506665          if (operandType is SetType) {
 9006666            return BinaryExpr.ResolvedOpcode.Union;
 157706667          } else if (operandType is MultiSetType) {
 9206668            return BinaryExpr.ResolvedOpcode.MultiSetUnion;
 139306669          } else if (operandType is MapType) {
 06670            return BinaryExpr.ResolvedOpcode.MapMerge;
 144206671          } else if (operandType is SeqType) {
 4906672            return BinaryExpr.ResolvedOpcode.Concat;
 134406673          } else {
 134406674            return BinaryExpr.ResolvedOpcode.Add;
 6675          }
 6676        case BinaryExpr.Opcode.Sub:
 14406677          if (leftOperandType is MapType) {
 06678            return BinaryExpr.ResolvedOpcode.MapSubtraction;
 21206679          } else if (operandType is SetType) {
 6806680            return BinaryExpr.ResolvedOpcode.SetDifference;
 13906681          } else if (operandType is MultiSetType) {
 6306682            return BinaryExpr.ResolvedOpcode.MultiSetDifference;
 1306683          } else {
 1306684            return BinaryExpr.ResolvedOpcode.Sub;
 6685          }
 6686        case BinaryExpr.Opcode.Mul:
 17706687          if (operandType is SetType) {
 8306688            return BinaryExpr.ResolvedOpcode.Intersection;
 1106689          } else if (operandType is MultiSetType) {
 06690            return BinaryExpr.ResolvedOpcode.MultiSetIntersection;
 1106691          } else {
 1106692            return BinaryExpr.ResolvedOpcode.Mul;
 6693          }
 6694        case BinaryExpr.Opcode.Gt:
 7706695          if (operandType.IsDatatype) {
 06696            return BinaryExpr.ResolvedOpcode.RankGt;
 9106697          } else if (operandType is SetType) {
 1406698            return BinaryExpr.ResolvedOpcode.ProperSuperset;
 7106699          } else if (operandType is MultiSetType) {
 806700            return BinaryExpr.ResolvedOpcode.ProperMultiSuperset;
 6906701          } else if (operandType is CharType) {
 1406702            return BinaryExpr.ResolvedOpcode.GtChar;
 4106703          } else {
 4106704            return BinaryExpr.ResolvedOpcode.Gt;
 6705          }
 6706        case BinaryExpr.Opcode.Ge:
 7106707          if (operandType is SetType) {
 1406708            return BinaryExpr.ResolvedOpcode.Superset;
 5906709          } else if (operandType is MultiSetType) {
 1606710            return BinaryExpr.ResolvedOpcode.MultiSuperset;
 4606711          } else if (operandType is CharType) {
 1906712            return BinaryExpr.ResolvedOpcode.GeChar;
 806713          } else {
 806714            return BinaryExpr.ResolvedOpcode.Ge;
 6715          }
 6716        case BinaryExpr.Opcode.In:
 12406717          if (operandType is SetType) {
 3506718            return BinaryExpr.ResolvedOpcode.InSet;
 8506719          } else if (operandType is MultiSetType) {
 3106720            return BinaryExpr.ResolvedOpcode.InMultiSet;
 2306721          } else if (operandType is MapType) {
 06722            return BinaryExpr.ResolvedOpcode.InMap;
 2306723          } else {
 2306724            return BinaryExpr.ResolvedOpcode.InSeq;
 6725          }
 6726        case BinaryExpr.Opcode.NotIn:
 10406727          if (operandType is SetType) {
 2606728            return BinaryExpr.ResolvedOpcode.NotInSet;
 7906729          } else if (operandType is MultiSetType) {
 2706730            return BinaryExpr.ResolvedOpcode.NotInMultiSet;
 2506731          } else if (operandType is MapType) {
 06732            return BinaryExpr.ResolvedOpcode.NotInMap;
 2506733          } else {
 2506734            return BinaryExpr.ResolvedOpcode.NotInSeq;
 6735          }
 8306736        case BinaryExpr.Opcode.Div: return BinaryExpr.ResolvedOpcode.Div;
 8306737        case BinaryExpr.Opcode.Mod: return BinaryExpr.ResolvedOpcode.Mod;
 06738        case BinaryExpr.Opcode.BitwiseAnd: return BinaryExpr.ResolvedOpcode.BitwiseAnd;
 06739        case BinaryExpr.Opcode.BitwiseOr: return BinaryExpr.ResolvedOpcode.BitwiseOr;
 06740        case BinaryExpr.Opcode.BitwiseXor: return BinaryExpr.ResolvedOpcode.BitwiseXor;
 6741        default:
 06742          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 6743      }
 655306744    }
 6745
 6746    /// <summary>
 6747    /// This method adds to "friendlyCalls" all
 6748    ///     inductive calls                                     if !co
 6749    ///     greatest predicate calls and codatatype equalities  if co
 6750    /// that occur in positive positions and not under
 6751    ///     universal quantification                            if !co
 6752    ///     existential quantification.                         if co
 6753    /// If "expr" is the
 6754    ///     precondition of a least lemma                       if !co
 6755    ///     postcondition of a greatest lemma,                  if co
 6756    /// then the "friendlyCalls" are the subexpressions that need to be replaced in order
 6757    /// to create the
 6758    ///     precondition                                        if !co
 6759    ///     postcondition                                       if co
 6760    /// of the corresponding prefix lemma.
 6761    /// </summary>
 06762    void CollectFriendlyCallsInExtremeLemmaSpecification(Expression expr, bool position, ISet<Expression> friendlyCalls,
 6763      Contract.Requires(expr != null);
 6764      Contract.Requires(friendlyCalls != null);
 06765      var visitor = new CollectFriendlyCallsInSpec_Visitor(this, friendlyCalls, co, context);
 06766      visitor.Visit(expr, position ? CallingPosition.Positive : CallingPosition.Negative);
 06767    }
 6768
 6769    class CollectFriendlyCallsInSpec_Visitor : FindFriendlyCalls_Visitor {
 6770      readonly ISet<Expression> friendlyCalls;
 6771      readonly ExtremeLemma Context;
 6772      public CollectFriendlyCallsInSpec_Visitor(Resolver resolver, ISet<Expression> friendlyCalls, bool co, ExtremeLemma
 06773        : base(resolver, co, context.KNat) {
 6774        Contract.Requires(resolver != null);
 6775        Contract.Requires(friendlyCalls != null);
 6776        Contract.Requires(context != null);
 06777        this.friendlyCalls = friendlyCalls;
 06778        this.Context = context;
 06779      }
 06780      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 06781        if (cp == CallingPosition.Neither) {
 6782          // no friendly calls in "expr"
 06783          return false;  // don't recurse into subexpressions
 6784        }
 06785        if (expr is FunctionCallExpr) {
 06786          if (cp == CallingPosition.Positive) {
 06787            var fexp = (FunctionCallExpr)expr;
 06788            if (IsCoContext ? fexp.Function is GreatestPredicate : fexp.Function is LeastPredicate) {
 06789              if (Context.KNat != ((ExtremePredicate)fexp.Function).KNat) {
 06790                resolver.KNatMismatchError(expr.tok, Context.Name, Context.TypeOfK, ((ExtremePredicate)fexp.Function).Ty
 06791              } else {
 06792                friendlyCalls.Add(fexp);
 06793              }
 06794            }
 06795          }
 06796          return false;  // don't explore subexpressions any further
 06797        } else if (expr is BinaryExpr && IsCoContext) {
 06798          var bin = (BinaryExpr)expr;
 06799          if (cp == CallingPosition.Positive && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon && bin.E0.Type.IsCo
 06800            friendlyCalls.Add(bin);
 06801            return false;  // don't explore subexpressions any further
 06802          } else if (cp == CallingPosition.Negative && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon && bin.E0.T
 06803            friendlyCalls.Add(bin);
 06804            return false;  // don't explore subexpressions any further
 6805          }
 06806        }
 06807        return base.VisitOneExpr(expr, ref cp);
 06808      }
 6809    }
 6810  }
 6811
 6812  abstract class ResolverTopDownVisitor<T> : TopDownVisitor<T> {
 6813    protected Resolver resolver;
 6814    public ResolverTopDownVisitor(Resolver resolver) {
 6815      Contract.Requires(resolver != null);
 6816      this.resolver = resolver;
 6817    }
 6818  }
 6819
 6820  class CoCallResolution {
 6821    readonly Function currentFunction;
 6822    readonly bool dealsWithCodatatypes;
 6823    public bool HasIntraClusterCallsInDestructiveContexts = false;
 6824    public readonly List<CoCallInfo> FinalCandidates = new List<CoCallInfo>();
 6825
 6826    public CoCallResolution(Function currentFunction, bool dealsWithCodatatypes) {
 6827      Contract.Requires(currentFunction != null);
 6828      this.currentFunction = currentFunction;
 6829      this.dealsWithCodatatypes = dealsWithCodatatypes;
 6830    }
 6831
 6832    /// <summary>
 6833    /// Determines which calls in "expr" can be considered to be co-calls, which co-constructor
 6834    /// invocations host such co-calls, and which destructor operations are not allowed.
 6835    /// Also records whether or not there are any intra-cluster calls in a destructive context.
 6836    /// Assumes "expr" to have been successfully resolved.
 6837    /// </summary>
 6838    public void CheckCoCalls(Expression expr) {
 6839      Contract.Requires(expr != null);
 6840      CheckCoCalls(expr, 0, null, FinalCandidates);
 6841    }
 6842
 6843    public struct CoCallInfo {
 6844      public readonly FunctionCallExpr CandidateCall;
 6845      public readonly DatatypeValue EnclosingCoConstructor;
 6846      public CoCallInfo(FunctionCallExpr candidateCall, DatatypeValue enclosingCoConstructor) {
 6847        Contract.Requires(candidateCall != null);
 6848        Contract.Requires(enclosingCoConstructor != null);
 6849        CandidateCall = candidateCall;
 6850        EnclosingCoConstructor = enclosingCoConstructor;
 6851      }
 6852    }
 6853
 6854    /// <summary>
 6855    /// Recursively goes through the entire "expr".  Every call within the same recursive cluster is a potential
 6856    /// co-call.  If the call is determined not to be a co-recursive call, then its .CoCall field is filled in;
 6857    /// if the situation deals with co-datatypes, then one of the NoBecause... values is chosen (rather
 6858    /// than just No), so that any error message that may later be produced when trying to prove termination of the
 6859    /// recursive call can include a note pointing out that the call was not selected to be a co-call.
 6860    /// If the call looks like it is guarded, then it is added to the list "coCandicates", so that a later analysis
 6861    /// can either set all of those .CoCall fields to Yes or to NoBecauseRecursiveCallsInDestructiveContext, depending
 6862    /// on other intra-cluster calls.
 6863    /// The "destructionLevel" indicates how many pending co-destructors the context has.  It may be infinity (int.MaxVa
 6864    /// if the enclosing context has no easy way of controlling the uses of "expr" (for example, if the enclosing contex
 6865    /// passes "expr" to a function or binds "expr" to a variable).  It is never negative -- excess co-constructors are
 6866    /// not considered an asset, and any immediately enclosing co-constructor is passed in as a non-null "coContext" any
 6867    /// "coContext" is non-null if the immediate context is a co-constructor.
 6868    /// </summary>
 6869    void CheckCoCalls(Expression expr, int destructionLevel, DatatypeValue coContext, List<CoCallInfo> coCandidates, Fun
 6870      Contract.Requires(expr != null);
 6871
 6872      Contract.Requires(0 <= destructionLevel);
 6873      Contract.Requires(coCandidates != null);
 6874      expr = expr.Resolved;
 6875      if (expr is DatatypeValue) {
 6876        var e = (DatatypeValue)expr;
 6877        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 6878          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel == 0 ? 0 : destructionLevel - 1;
 6879          foreach (var arg in e.Arguments) {
 6880            CheckCoCalls(arg, dl, e, coCandidates);
 6881          }
 6882          return;
 6883        }
 6884      } else if (expr is MemberSelectExpr) {
 6885        var e = (MemberSelectExpr)expr;
 6886        if (e.Member.EnclosingClass is CoDatatypeDecl) {
 6887          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel + 1;
 6888          CheckCoCalls(e.Obj, dl, coContext, coCandidates);
 6889          return;
 6890        }
 6891      } else if (expr is BinaryExpr) {
 6892        var e = (BinaryExpr)expr;
 6893        if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon || e.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon) {
 6894          // Equality and disequality (for any type that may contain a co-datatype) are as destructive as can be--in ess
 6895          // they destruct the values indefinitely--so don't allow any co-recursive calls in the operands.
 6896          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6897          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6898          return;
 6899        }
 6900      } else if (expr is TernaryExpr) {
 6901        var e = (TernaryExpr)expr;
 6902        if (e.Op == TernaryExpr.Opcode.PrefixEqOp || e.Op == TernaryExpr.Opcode.PrefixNeqOp) {
 6903          // Prefix equality and disequality (for any type that may contain a co-datatype) are destructive.
 6904          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6905          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6906          CheckCoCalls(e.E2, int.MaxValue, null, coCandidates);
 6907          return;
 6908        }
 6909      } else if (expr is NestedMatchExpr) {
 6910        var e = (NestedMatchExpr)expr;
 6911        foreach (var child in e.SubExpressions) {
 6912          CheckCoCalls(child, destructionLevel, coContext, coCandidates);
 6913        }
 6914      } else if (expr is MatchExpr) {
 6915        var e = (MatchExpr)expr;
 6916        CheckCoCalls(e.Source, int.MaxValue, null, coCandidates);
 6917        foreach (var kase in e.Cases) {
 6918          CheckCoCalls(kase.Body, destructionLevel, coContext, coCandidates);
 6919        }
 6920        return;
 6921      } else if (expr is ITEExpr) {
 6922        var e = (ITEExpr)expr;
 6923        CheckCoCalls(e.Test, int.MaxValue, null, coCandidates);
 6924        CheckCoCalls(e.Thn, destructionLevel, coContext, coCandidates);
 6925        CheckCoCalls(e.Els, destructionLevel, coContext, coCandidates);
 6926        return;
 6927      } else if (expr is FunctionCallExpr) {
 6928        var e = (FunctionCallExpr)expr;
 6929        // First, consider the arguments of the call, making sure that they do not include calls within the recursive cl
 6930        // unless the callee is abstemious.
 6931        var abstemious = true;
 6932        if (!Attributes.ContainsBool(e.Function.Attributes, "abstemious", ref abstemious)) {
 6933          abstemious = false;
 6934        }
 6935        Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 6936        for (var i = 0; i < e.Args.Count; i++) {
 6937          var arg = e.Args[i];
 6938          if (!e.Function.Formals[i].Type.IsCoDatatype) {
 6939            CheckCoCalls(arg, int.MaxValue, null, coCandidates);
 6940          } else if (abstemious) {
 6941            CheckCoCalls(arg, 0, coContext, coCandidates);
 6942          } else {
 6943            // don't you wish the callee were abstemious
 6944            CheckCoCalls(arg, int.MaxValue, null, coCandidates, e.Function);
 6945          }
 6946        }
 6947        // Second, investigate the possibility that this call itself may be a candidate co-call
 6948        if (e.Name != "requires" && ModuleDefinition.InSameSCC(currentFunction, e.Function)) {
 6949          // This call goes to another function in the same recursive cluster
 6950          if (destructionLevel != 0 && GuaranteedCoCtors(e.Function) <= destructionLevel) {
 6951            // a potentially destructive context
 6952            HasIntraClusterCallsInDestructiveContexts = true;  // this says we found an intra-cluster call unsuitable fo
 6953            if (!dealsWithCodatatypes) {
 6954              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6955            } else {
 6956              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsAreNotAllowedInThisContext;
 6957              if (functionYouMayWishWereAbstemious != null) {
 6958                e.CoCallHint = string.Format("perhaps try declaring function '{0}' with '{{:abstemious}}'", functionYouM
 6959              }
 6960            }
 6961          } else if (coContext == null) {
 6962            // no immediately enclosing co-constructor
 6963            if (!dealsWithCodatatypes) {
 6964              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6965            } else {
 6966              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseIsNotGuarded;
 6967            }
 6968          } else if (e.Function.Reads.Count != 0) {
 6969            // this call is disqualified from being a co-call, because of side effects
 6970            if (!dealsWithCodatatypes) {
 6971              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6972            } else {
 6973              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasSideEffects;
 6974            }
 6975          } else if (e.Function.Ens.Count != 0) {
 6976            // this call is disqualified from being a co-call, because it has a postcondition
 6977            // (a postcondition could be allowed, as long as it does not get to be used with
 6978            // co-recursive calls, because that could be unsound; for example, consider
 6979            // "ensures false")
 6980            if (!dealsWithCodatatypes) {
 6981              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6982            } else {
 6983              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasPostcondition;
 6984            }
 6985          } else {
 6986            // e.CoCall is not filled in here, but will be filled in when the list of candidates are processed
 6987            coCandidates.Add(new CoCallInfo(e, coContext));
 6988          }
 6989        }
 6990        return;
 6991      } else if (expr is LambdaExpr) {
 6992        var e = (LambdaExpr)expr;
 6993        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 6994        if (e.Range != null) {
 6995          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 6996        }
 6997        foreach (var read in e.Reads) {
 6998          CheckCoCalls(read.E, int.MaxValue, null, coCandidates);
 6999        }
 7000        return;
 7001      } else if (expr is MapComprehension) {
 7002        var e = (MapComprehension)expr;
 7003        foreach (var ee in Attributes.SubExpressions(e.Attributes)) {
 7004          CheckCoCalls(ee, int.MaxValue, null, coCandidates);
 7005        }
 7006        if (e.Range != null) {
 7007          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 7008        }
 7009        // allow co-calls in the term
 7010        if (e.TermLeft != null) {
 7011          CheckCoCalls(e.TermLeft, destructionLevel, coContext, coCandidates);
 7012        }
 7013        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 7014        return;
 7015      } else if (expr is OldExpr) {
 7016        var e = (OldExpr)expr;
 7017        // here, "coContext" is passed along (the use of "old" says this must be ghost code, so the compiler does not ne
 7018        CheckCoCalls(e.E, destructionLevel, coContext, coCandidates);
 7019        return;
 7020      } else if (expr is LetExpr) {
 7021        var e = (LetExpr)expr;
 7022        foreach (var rhs in e.RHSs) {
 7023          CheckCoCalls(rhs, int.MaxValue, null, coCandidates);
 7024        }
 7025        CheckCoCalls(e.Body, destructionLevel, coContext, coCandidates);
 7026        return;
 7027      } else if (expr is ApplyExpr) {
 7028        var e = (ApplyExpr)expr;
 7029        CheckCoCalls(e.Function, int.MaxValue, null, coCandidates);
 7030        foreach (var ee in e.Args) {
 7031          CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7032        }
 7033        return;
 7034      }
 7035
 7036      // Default handling:
 7037      foreach (var ee in expr.SubExpressions) {
 7038        CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7039      }
 7040    }
 7041
 7042    public static int GuaranteedCoCtors(Function function) {
 7043      Contract.Requires(function != null);
 7044      return function.Body != null ? GuaranteedCoCtorsAux(function.Body) : 0;
 7045    }
 7046
 7047    private static int GuaranteedCoCtorsAux(Expression expr) {
 7048      Contract.Requires(expr != null);
 7049      expr = expr.Resolved;
 7050      if (expr is DatatypeValue) {
 7051        var e = (DatatypeValue)expr;
 7052        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 7053          var minOfArgs = int.MaxValue;  // int.MaxValue means: not yet encountered a formal whose type is a co-datatype
 7054          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 7055          for (var i = 0; i < e.Arguments.Count; i++) {
 7056            if (e.Ctor.Formals[i].Type.IsCoDatatype) {
 7057              var n = GuaranteedCoCtorsAux(e.Arguments[i]);
 7058              minOfArgs = Math.Min(minOfArgs, n);
 7059            }
 7060          }
 7061          return minOfArgs == int.MaxValue ? 1 : 1 + minOfArgs;
 7062        }
 7063      } else if (expr is ITEExpr) {
 7064        var e = (ITEExpr)expr;
 7065        var thn = GuaranteedCoCtorsAux(e.Thn);
 7066        var els = GuaranteedCoCtorsAux(e.Els);
 7067        return thn < els ? thn : els;
 7068      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 7069        var childValues = nestedMatchExpr.Cases.Select(child => GuaranteedCoCtorsAux(child.Body)).ToList();
 7070        return childValues.Any() ? childValues.Min() : 0;
 7071      } else if (expr is MatchExpr) {
 7072        var e = (MatchExpr)expr;
 7073        var min = int.MaxValue;
 7074        foreach (var kase in e.Cases) {
 7075          var n = GuaranteedCoCtorsAux(kase.Body);
 7076          min = Math.Min(min, n);
 7077        }
 7078        return min == int.MaxValue ? 0 : min;
 7079      } else if (expr is LetExpr) {
 7080        var e = (LetExpr)expr;
 7081        return GuaranteedCoCtorsAux(e.Body);
 7082      } else if (expr is IdentifierExpr) {
 7083        var e = (IdentifierExpr)expr;
 7084        if (e.Type.IsCoDatatype && e.Var is Formal) {
 7085          // even though this is not a co-constructor, count this as 1, since that's what we would have done if it were,
 7086          return 1;
 7087        }
 7088      }
 7089      return 0;
 7090    }
 7091  }
 7092}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/TypeInferenceChecker.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.Diagnostics.Contracts;
 3using System.Linq;
 4using System.Numerics;
 5using Microsoft.Boogie;
 6using static Microsoft.Dafny.ErrorRegistry;
 7
 8namespace Microsoft.Dafny;
 9
 10partial class Resolver {
 11  class TypeInferenceCheckingContext : IASTVisitorContext {
 12    private readonly IASTVisitorContext astVisitorContext;
 13
 459014    public bool IsPrefixPredicate => astVisitorContext is PrefixPredicate;
 1354015    public bool IsExtremePredicate => astVisitorContext is ExtremePredicate;
 38444016    public bool IsPrefixDeclaration => astVisitorContext is PrefixPredicate or PrefixLemma;
 17
 4009018    public TypeInferenceCheckingContext(IASTVisitorContext astVisitorContext) {
 2004519      this.astVisitorContext = astVisitorContext;
 2004520    }
 21
 844022    ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 23  }
 24
 25  class CheckTypeInferenceVisitor : ASTVisitor<TypeInferenceCheckingContext> {
 26    private readonly Resolver resolver;
 027    private ErrorReporter reporter => resolver.reporter;
 28
 249029    public CheckTypeInferenceVisitor(Resolver resolver) {
 124530      this.resolver = resolver;
 124531    }
 32
 2004533    public override TypeInferenceCheckingContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostcon
 2004534      return new TypeInferenceCheckingContext(astVisitorContext);
 2004535    }
 36
 249037    protected override void VisitOneDeclaration(TopLevelDecl decl) {
 249038      if (decl is NewtypeDecl newtypeDecl) {
 039        if (newtypeDecl.Var != null) {
 040          if (!IsDetermined(newtypeDecl.BaseType.NormalizeExpand())) {
 041            reporter.Error(MessageSource.Resolver, newtypeDecl.tok, "newtype's base type is not fully determined; add an
 042              newtypeDecl.Var.Name);
 043          }
 044        }
 45
 332046      } else if (decl is SubsetTypeDecl subsetTypeDecl) {
 83047        if (!IsDetermined(subsetTypeDecl.Rhs.NormalizeExpand())) {
 048          reporter.Error(MessageSource.Resolver, subsetTypeDecl.tok,
 049            "subset type's base type is not fully determined; add an explicit type for '{0}'", subsetTypeDecl.Var.Name);
 050        }
 51
 249052      } else if (decl is DatatypeDecl datatypeDecl) {
 053        foreach (var member in resolver.classMembers[datatypeDecl].Values) {
 054          if (member is DatatypeDestructor dtor) {
 055            var rolemodel = dtor.CorrespondingFormals[0];
 056            for (var i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 057              var other = dtor.CorrespondingFormals[i];
 058              if (!Type.Equal_Improved(rolemodel.Type, other.Type)) {
 059                reporter.Error(MessageSource.Resolver, other,
 060                  "shared destructors must have the same type, but '{0}' has type '{1}' in constructor '{2}' and type '{
 061                  rolemodel.Name, rolemodel.Type, dtor.EnclosingCtors[0].Name, other.Type, dtor.EnclosingCtors[i].Name);
 062              }
 063            }
 064          }
 065        }
 066      }
 67
 249068      base.VisitOneDeclaration(decl);
 249069    }
 70
 41571    public override void VisitField(Field field) {
 41572      if (field is ConstantField constantField) {
 073        resolver.PartiallySolveTypeConstraints(true);
 074        CheckTypeIsDetermined(field.tok, field.Type, "const");
 075      }
 76
 41577      base.VisitField(field);
 41578    }
 79
 119880080    protected override bool VisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 119880081      if (stmt is CalcStmt calcStmt) {
 82        // The resolution of the calc statement builds up .Steps and .Result, which are of the form E0 OP E1, where
 83        // E0 and E1 are expressions from .Lines.  These additional expressions still need to have their .ResolvedOp
 84        // fields filled in, so we visit them, rather than just the parsed .Lines.
 085        Attributes.SubExpressions(calcStmt.Attributes).Iter(e => VisitExpression(e, context));
 086        calcStmt.Steps.Iter(e => VisitExpression(e, context));
 087        VisitExpression(calcStmt.Result, context);
 088        calcStmt.Hints.Iter(hint => VisitStatement(hint, context));
 089        return false; // we're done with all subcomponents of the CalcStmt
 90      }
 91
 119880092      return base.VisitOneStatement(stmt, context);
 119880093    }
 94
 119880095    protected override void PostVisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 153885096      if (stmt is VarDeclStmt) {
 34005097        var s = (VarDeclStmt)stmt;
 205797098        foreach (var local in s.Locals) {
 34594099          CheckTypeIsDetermined(local.Tok, local.Type, "local variable");
 345940100          CheckTypeArgsContainNoOrdinal(local.Tok, local.type, context);
 345940101        }
 1198800102      } else if (stmt is VarDeclPattern) {
 0103        var s = (VarDeclPattern)stmt;
 0104        s.LocalVars.Iter(local => CheckTypeIsDetermined(local.Tok, local.Type, "local variable"));
 0105        s.LocalVars.Iter(local => CheckTypeArgsContainNoOrdinal(local.Tok, local.Type, context));
 106
 858750107      } else if (stmt is ForallStmt) {
 0108        var s = (ForallStmt)stmt;
 0109        s.BoundVars.Iter(bv => CheckTypeIsDetermined(bv.tok, bv.Type, "bound variable"));
 0110        s.BoundVars.Iter(bv => CheckTypeArgsContainNoOrdinal(bv.tok, bv.Type, context));
 111
 858750112      } else if (stmt is AssignSuchThatStmt) {
 0113        var s = (AssignSuchThatStmt)stmt;
 0114        foreach (var lhs in s.Lhss) {
 0115          CheckTypeArgsContainNoOrdinal(lhs.tok, lhs.Type, context);
 0116        }
 0117      }
 118
 1198800119      base.PostVisitOneStatement(stmt, context);
 1198800120    }
 121
 2769855122    protected override void PostVisitOneExpression(Expression expr, TypeInferenceCheckingContext context) {
 3098435123      if (expr is LiteralExpr) {
 328580124        var e = (LiteralExpr)expr;
 328580125        if (e.Type.IsBitVectorType || e.Type.IsBigOrdinalType) {
 0126          var n = (BigInteger)e.Value;
 0127          var absN = n < 0 ? -n : n;
 128          // For bitvectors, check that the magnitude fits the width
 0129          if (e.Type.IsBitVectorType && MaxBV(e.Type.AsBitVectorType.Width) < absN) {
 0130            resolver.reporter.Error(MessageSource.Resolver, e.tok, "literal ({0}) is too large for the bitvector type {1
 0131          }
 132          // For bitvectors and ORDINALs, check for a unary minus that, earlier, was mistaken for a negative literal
 133          // This can happen only in `match` patterns (see comment by LitPattern.OptimisticallyDesugaredLit).
 0134          if (n < 0 || e.tok.val == "-0") {
 0135            Contract.Assert(e.tok.val == "-0");  // this and the "if" above tests that "n < 0" happens only when the tok
 0136            resolver.reporter.Error(MessageSource.Resolver, e.tok, "unary minus (-{0}, type {1}) not allowed in case pat
 0137          }
 0138        }
 139
 350580140        if (expr is StaticReceiverExpr stexpr) {
 66000141          foreach (Type t in stexpr.Type.TypeArgs) {
 0142            if (t is InferredTypeProxy && ((InferredTypeProxy)t).T == null) {
 0143              resolver.reporter.Error(MessageSource.Resolver, stexpr.tok, "type of type parameter could not be determine
 0144            }
 0145          }
 22000146        }
 147
 2775215148      } else if (expr is ComprehensionExpr) {
 5360149        var e = (ComprehensionExpr)expr;
 56700150        foreach (var bv in e.BoundVars) {
 13540151          if (!IsDetermined(bv.Type.Normalize())) {
 0152            resolver.reporter.Error(MessageSource.Resolver, bv.tok,
 0153              $"type of bound variable '{bv.Name}' could not be determined; please specify the type explicitly");
 13540154          } else if (context.IsExtremePredicate) {
 0155            CheckContainsNoOrdinal(bv.tok, bv.Type, $"type of bound variable '{bv.Name}' ('{bv.Type}') is not allowed to
 0156          }
 13540157        }
 158
 5360159        if (e is ExistsExpr && e.Range == null) {
 0160          var binBody = ((ExistsExpr)e).Term as BinaryExpr;
 0161          if (binBody != null && binBody.Op == BinaryExpr.Opcode.Imp) {  // check Op, not ResolvedOp, in order to distin
 162                                                                         // apply the wisdom of Claude Marche: issue a w
 0163            resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0164              "the quantifier has the form 'exists x :: A ==> B', which most often is a typo for 'exists x :: A && B'; "
 0165              "if you think otherwise, rewrite as 'exists x :: (A ==> B)' or 'exists x :: !A || B' to suppress this warn
 0166          }
 0167        }
 168
 2464555169      } else if (expr is MemberSelectExpr) {
 23280170        var e = (MemberSelectExpr)expr;
 37730171        if (e.Member is Function || e.Member is Method) {
 14450172          var i = 0;
 43350173          foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustMember)) {
 0174            var tp = i < e.TypeApplication_AtEnclosingClass.Count
 0175              ? e.Member.EnclosingClass.TypeArgs[i]
 0176              : ((ICallable)e.Member).TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 0177            if (!IsDetermined(p.Normalize())) {
 0178              resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0179                $"type parameter '{tp.Name}' (inferred to be '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' could n
 0180            } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat i
 0181              CheckContainsNoOrdinal(e.tok, p,
 0182                $"type parameter '{tp.Name}' (passed in as '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' is not al
 0183            }
 0184            i++;
 0185          }
 14450186        }
 2443465187      } else if (expr is FunctionCallExpr) {
 7550188        var e = (FunctionCallExpr)expr;
 7550189        var i = 0;
 36420190        foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustFunction)) {
 4590191          var tp = i < e.TypeApplication_AtEnclosingClass.Count
 4590192            ? e.Function.EnclosingClass.TypeArgs[i]
 4590193            : e.Function.TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 4590194          if (!IsDetermined(p.Normalize())) {
 0195            var hint = e.Name.StartsWith("reveal_")
 0196              ? ". If you are making an opaque function, make sure that the function can be called."
 0197              : "";
 0198            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0199              $"type parameter '{tp.Name}' (inferred to be '{p}') in the function call to '{e.Name}' could not be determ
 9180200          } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat it 
 4590201            CheckContainsNoOrdinal(e.tok, p,
 4590202              $"type parameter '{tp.Name}' (passed in as '{p}') to function call '{e.Name}' is not allowed to use ORDINA
 4590203          }
 4590204          i++;
 4590205        }
 2451135206      } else if (expr is LetExpr) {
 38500207        var e = (LetExpr)expr;
 231000208        foreach (var p in e.LHSs) {
 231000209          foreach (var x in p.Vars) {
 38500210            if (!IsDetermined(x.Type.Normalize())) {
 0211              resolver.reporter.Error(MessageSource.Resolver, x.tok, $"the type of the bound variable '{x.Name}' could n
 38500212            } else {
 38500213              CheckTypeArgsContainNoOrdinal(x.tok, x.Type, context);
 38500214            }
 38500215          }
 38500216        }
 3534955217      } else if (expr is IdentifierExpr) {
 218        // by specializing for IdentifierExpr, error messages will be clearer
 1129870219        CheckTypeIsDetermined(expr.tok, expr.Type, "variable");
 2367395220      } else if (expr is ConversionExpr) {
 810221        var e = (ConversionExpr)expr;
 810222        if (e.ToType.IsRefType) {
 0223          var fromType = e.E.Type;
 0224          Contract.Assert(fromType.IsRefType);
 0225          if (fromType.IsSubtypeOf(e.ToType, false, true) || e.ToType.IsSubtypeOf(fromType, false, true)) {
 226            // looks good
 0227          } else {
 0228            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0229              "a type cast to a reference type ({0}) must be from a compatible type (got {1}); this cast could never suc
 0230              e.ToType, fromType);
 0231          }
 0232        }
 1236715233      } else if (expr is TypeTestExpr) {
 0234        var e = (TypeTestExpr)expr;
 0235        var fromType = e.E.Type;
 0236        if (fromType.IsSubtypeOf(e.ToType, false, true)) {
 237          // This test is allowed and it always returns true
 0238        } else if (!e.ToType.IsSubtypeOf(fromType, false, true)) {
 0239          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0240            "a type test to '{0}' must be from a compatible type (got '{1}')", e.ToType, fromType);
 0241        } else if (!e.ToType.IsRefType) {
 0242          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0243            "a non-trivial type test is allowed only for reference types (tried to test if '{1}' is a '{0}')", e.ToType,
 0244        }
 2471810245      } else if (CheckTypeIsDetermined(expr.tok, expr.Type, "expression")) {
 1245285246        if (expr is UnaryOpExpr uop) {
 247          // The CheckTypeInference_Visitor has already visited uop.E, but uop.E's may be undetermined. If that happened
 248          // then an error has already been reported.
 18760249          if (CheckTypeIsDetermined(uop.E.tok, uop.E.Type, "expression")) {
 9380250            uop.ResolveOp(); // Force resolution eagerly at this point to catch potential bugs
 9380251          }
 1301435252        } else if (expr is BinaryExpr) {
 65530253          var e = (BinaryExpr)expr;
 65530254          e.ResolvedOp = ResolveOp(e.Op, e.E0.Type, e.E1.Type);
 255          // Check for useless comparisons with "null"
 65530256          Expression other = null;  // if "null" if one of the operands, then "other" is the other
 65530257          if (e.E0 is LiteralExpr && ((LiteralExpr)e.E0).Value == null) {
 0258            other = e.E1;
 66360259          } else if (e.E1 is LiteralExpr && ((LiteralExpr)e.E1).Value == null) {
 830260            other = e.E0;
 830261          }
 66360262          if (other != null) {
 830263            bool sense = true;
 830264            switch (e.ResolvedOp) {
 265              case BinaryExpr.ResolvedOpcode.NeqCommon:
 830266                sense = false;
 830267                goto case BinaryExpr.ResolvedOpcode.EqCommon;
 830268              case BinaryExpr.ResolvedOpcode.EqCommon: {
 830269                  var nntUdf = other.Type.AsNonNullRefType;
 830270                  if (nntUdf != null) {
 0271                    string name = null;
 0272                    string hint = "";
 0273                    other = other.Resolved;
 0274                    if (other is IdentifierExpr) {
 0275                      name = $"variable '{((IdentifierExpr)other).Name}'";
 0276                    } else if (other is MemberSelectExpr) {
 0277                      var field = ((MemberSelectExpr)other).Member as Field;
 278                      // The type of the field may be a formal type parameter, in which case the hint is omitted
 0279                      if (field.Type.IsNonNullRefType) {
 0280                        name = $"field '{field.Name}'";
 0281                      }
 0282                    }
 0283                    if (name != null) {
 284                      // The following relies on that a NonNullTypeDecl has a .Rhs that is a
 285                      // UserDefinedType denoting the possibly null type declaration and that
 286                      // these two types have the same number of type arguments.
 0287                      var nonNullTypeDecl = (NonNullTypeDecl)nntUdf.ResolvedClass;
 0288                      var possiblyNullUdf = (UserDefinedType)nonNullTypeDecl.Rhs;
 0289                      var possiblyNullTypeDecl = (ClassDecl)possiblyNullUdf.ResolvedClass;
 0290                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == possiblyNullTypeDecl.TypeArgs.Count);
 0291                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == nntUdf.TypeArgs.Count);
 0292                      var ty = new UserDefinedType(nntUdf.tok, possiblyNullUdf.Name, possiblyNullTypeDecl, nntUdf.TypeAr
 293
 0294                      hint = $" (to make it possible for {name} to have the value 'null', declare its type to be '{ty}')
 0295                    }
 0296                    var b = sense ? "false" : "true";
 0297                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0298                      $"the type of the other operand is a non-null type, so this comparison with 'null' will always ret
 0299                  }
 830300                  break;
 301                }
 302              case BinaryExpr.ResolvedOpcode.NotInSet:
 303              case BinaryExpr.ResolvedOpcode.NotInSeq:
 304              case BinaryExpr.ResolvedOpcode.NotInMultiSet:
 0305                sense = false;
 0306                goto case BinaryExpr.ResolvedOpcode.InSet;
 307              case BinaryExpr.ResolvedOpcode.InSet:
 308              case BinaryExpr.ResolvedOpcode.InSeq:
 0309              case BinaryExpr.ResolvedOpcode.InMultiSet: {
 0310                  var ty = other.Type.NormalizeExpand();
 0311                  var what = ty is SetType ? "set" : ty is SeqType ? "seq" : "multiset";
 0312                  if (((CollectionType)ty).Arg.IsNonNullRefType) {
 0313                    var non = sense ? "" : "non-";
 0314                    var b = sense ? "false" : "true";
 0315                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0316                      $"the type of the other operand is a {what} of non-null elements, so the {non}inclusion test of 'n
 0317                  }
 0318                  break;
 319                }
 320              case BinaryExpr.ResolvedOpcode.NotInMap:
 0321                goto case BinaryExpr.ResolvedOpcode.InMap;
 0322              case BinaryExpr.ResolvedOpcode.InMap: {
 0323                  var ty = other.Type.NormalizeExpand();
 0324                  if (((MapType)ty).Domain.IsNonNullRefType) {
 0325                    var b = sense ? "false" : "true";
 0326                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0327                      $"the type of the other operand is a map to a non-null type, so the inclusion test of 'null' will 
 0328                  }
 0329                  break;
 330                }
 331              default:
 0332                break;
 333            }
 830334          }
 1263585335        } else if (expr is NegationExpression) {
 37060336          var e = (NegationExpression)expr;
 37060337          Expression resolved = null;
 73290338          if (e.E is LiteralExpr lit) { // note, not e.E.Resolved, since we don't want to do this for double negations
 339                                        // For real-based types, integer-based types, and bi (but not bitvectors), "-" f
 340                                        // just a literal expression with a negative value
 36230341            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 0342              var d = (BaseTypes.BigDec)lit.Value;
 0343              Contract.Assert(!d.IsNegative);
 0344              resolved = new LiteralExpr(e.tok, -d);
 72460345            } else if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 36230346              var n = (BigInteger)lit.Value;
 36230347              Contract.Assert(0 <= n);
 36230348              resolved = new LiteralExpr(e.tok, -n);
 36230349            }
 36230350          }
 37890351          if (resolved == null) {
 352            // Treat all other expressions "-e" as "0 - e"
 353            Expression zero;
 830354            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 0355              zero = new LiteralExpr(e.tok, BaseTypes.BigDec.ZERO);
 830356            } else {
 830357              Contract.Assert(e.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || e.E.Type.IsBitVectorType);
 830358              zero = new LiteralExpr(e.tok, 0);
 830359            }
 830360            zero.Type = expr.Type;
 830361            resolved = new BinaryExpr(e.tok, BinaryExpr.Opcode.Sub, zero, e.E) { ResolvedOp = BinaryExpr.ResolvedOpcode.
 830362          }
 37060363          resolved.Type = expr.Type;
 37060364          e.ResolvedExpression = resolved;
 37060365        }
 1235905366      }
 367
 2769855368      base.PostVisitOneExpression(expr, context);
 2769855369    }
 370
 0371    protected override void VisitExtendedPattern(ExtendedPattern pattern, TypeInferenceCheckingContext context) {
 0372      base.VisitExtendedPattern(pattern, context);
 373
 0374      if (pattern is IdPattern { BoundVar: { } bv }) {
 0375        CheckTypeIsDetermined(bv.Tok, bv.Type, "bound variable");
 0376      }
 0377    }
 378
 567406355379    public static bool IsDetermined(Type t) {
 380      Contract.Requires(t != null);
 381      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);
 382      // all other proxies indicate the type has not yet been determined, provided their type parameters have been
 572384410383      return !(t is TypeProxy) && t.TypeArgs.All(tt => IsDetermined(tt.Normalize()));
 567406355384    }
 385
 1245386    readonly ISet<TypeProxy> UnderspecifiedTypeProxies = new HashSet<TypeProxy>();
 387
 7151475388    public bool CheckTypeIsDetermined(IToken tok, Type t, string what) {
 389      Contract.Requires(tok != null);
 390      Contract.Requires(t != null);
 391      Contract.Requires(what != null);
 7151475392      t = t.NormalizeExpandKeepConstraints();
 393
 7151475394      if (t is TypeProxy) {
 0395        var proxy = (TypeProxy)t;
 0396        if (!UnderspecifiedTypeProxies.Contains(proxy)) {
 397          // report an error for this TypeProxy only once
 0398          resolver.reporter.Error(MessageSource.Resolver, tok, "the type of this {0} is underspecified", what);
 0399          UnderspecifiedTypeProxies.Add(proxy);
 0400        }
 0401        return false;
 402      }
 403      // Recurse on type arguments:
 11581855404      return t.TypeArgs.All(rg => CheckTypeIsDetermined(tok, rg, what));
 7151475405    }
 406
 384440407    public void CheckTypeArgsContainNoOrdinal(IToken tok, Type t, TypeInferenceCheckingContext context) {
 408      Contract.Requires(tok != null);
 409      Contract.Requires(t != null);
 384440410      if (context.IsPrefixDeclaration) {
 411        // User-provided expressions in extreme predicates/lemmas are checked in the extreme declarations, so need
 412        // need to do them here again for the prefix predicates/lemmas.
 384440413      } else {
 384440414        t = t.NormalizeExpand();
 720340415        t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, "an ORDINAL type is not allowed to be used as a type argum
 384440416      }
 384440417    }
 418
 696140419    public void CheckContainsNoOrdinal(IToken tok, Type t, string errMsg) {
 420      Contract.Requires(tok != null);
 421      Contract.Requires(t != null);
 422      Contract.Requires(errMsg != null);
 696140423      t = t.NormalizeExpand();
 696140424      if (t.IsBigOrdinalType) {
 0425        resolver.reporter.Error(MessageSource.Resolver, tok, errMsg);
 0426      }
 1051790427      t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, errMsg));
 696140428    }
 429  }
 430}

Methods/Properties

get_AllowedToDependOnAllocationState()
get_Kind()
.ctor(Microsoft.Dafny.IASTVisitorContext)
.ctor(Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext,Microsoft.Dafny.LambdaExpr)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
.ctor(Microsoft.Dafny.ErrorReporter)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitTopLevelFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DesugarFunctionsInFrameClause(Microsoft.Dafny.FrameExpression)
FrameArrowToObjectSet(Microsoft.Dafny.Expression)
VisitExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DiscoverBestBounds_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverBestBounds_MultipleVars_AllowReordering(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_Aux_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_SingleVar(VT,Microsoft.Dafny.Expression)
DiscoverAllBounds_Aux_SingleVar(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
DiscoverBoundsFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,VT,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
NormalizedConjuncts()
SanitizeForBoundDiscovery(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.BinaryExpr/ResolvedOpcode,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
IsMonotonic(Microsoft.Dafny.Expression,Microsoft.Dafny.IVariable,System.Boolean)
ResolveNamesAndInferTypes(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,System.Boolean)
ResolveNamesAndInferTypesForOneDeclarationInitial(Microsoft.Dafny.TopLevelDecl)
ResolveNamesAndInferTypesForOneDeclaration(Microsoft.Dafny.TopLevelDecl)
EagerAddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression,System.String)
PrintTypeConstraintState(System.Int32)
SolveAllTypeConstraints()
ResolveAttributes(Microsoft.Dafny.IAttributeBearingDeclaration,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveTypeParameters(System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean,Microsoft.Dafny.TypeParameter/ParentType)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,System.String,System.Object[])
ConstrainTypeExprBool(Microsoft.Dafny.Expression,System.String)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.IToken,System.String,System.Object[])
ConstrainAssignable(Microsoft.Dafny.NonProxyType,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&,System.Boolean)
ConstrainAssignableTypeArgs(Microsoft.Dafny.Type,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&)
ConstrainSubtypeRelation_Equal(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean,System.Boolean)
ConstrainSubtypeRelation_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint,System.Boolean,System.Boolean)
DetermineRootLeaf(Microsoft.Dafny.Type,System.Boolean&,System.Boolean&,System.Boolean&,System.Boolean&)
.ctor(Microsoft.Dafny.DafnyOptions)
AssignProxyAndHandleItsConstraints(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
AssignProxyAndHandleItsConstraints_aux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
ImposeSubtypingConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainTypeHead_Recursive(Microsoft.Dafny.Type,Microsoft.Dafny.Type&)
ConstrainTypeHead(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
KeepConstraints(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
ToString()
Confirm(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean&,System.Boolean&)
ProxyWithNoSubTypeConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Resolver)
CouldBeAnything()
FindCollectionType(Microsoft.Dafny.DafnyOptions,Microsoft.Dafny.Type,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.Expression[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
PartiallySolveTypeConstraints(System.Boolean)
NewIntegerBasedProxy(Microsoft.Dafny.IToken)
ContainsAsTypeParameter(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
AddAllProxies(Microsoft.Dafny.Type,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ProcessAssignable(Microsoft.Dafny.TypeProxy,System.Collections.Generic.List`1<Microsoft.Dafny.Type>)
ConvertAssignableToSubtypeConstraints(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
TightenUpEquatable(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ProcessOneSubtypingConstraintAndItsSubs(Microsoft.Dafny.TypeConstraint,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeConstraint>,System.Boolean,System.Boolean&)
ProcessFullStrength_SubDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
ProcessFullStrength_SuperDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
AssignKnownEnd(Microsoft.Dafny.TypeProxy,System.Boolean,System.Boolean)
AssignKnownEndsFullstrength(Microsoft.Dafny.TypeProxy)
AssignKnownEndsFullstrength_SubDirection(Microsoft.Dafny.TypeProxy)
CloseOverAssignableRhss(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint_SubDirection(Microsoft.Dafny.TypeProxy)
HasApplicableNullableRefTypeConstraint_SubDirection_aux(Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
AssignKnownEndsFullstrength_SuperDirection(Microsoft.Dafny.TypeProxy)
Reaches(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
Reaches_aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ResolveClassMemberBodiesInitial(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberBodies(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveCtorTypes(Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
ResolveCtorSignature(Microsoft.Dafny.DatatypeCtor,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
AddDatatypeDependencyEdge(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Type,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ResolveFrameExpressionTopLevel(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ICodeContext)
ResolveFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ResolutionContext)
ResolveIterator(Microsoft.Dafny.IteratorDecl)
CheckIsLvalue(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveBlockStatement(Microsoft.Dafny.BlockStmt,Microsoft.Dafny.ResolutionContext)
ResolveStatementWithLabels(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveAlternatives(System.Collections.Generic.List`1<Microsoft.Dafny.GuardedAlternative>,Microsoft.Dafny.AlternativeLoopStmt,Microsoft.Dafny.ResolutionContext)
ResolveCallStmt(Microsoft.Dafny.CallStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Type)
ResolveActualParameters(Microsoft.Dafny.ActualBindings,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.IToken,System.Object,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Expression)
GetLocationInformation(Microsoft.Dafny.Formal,System.Int32,System.Int32,System.String)
ResolveDotSuffix_Type(Microsoft.Dafny.ExprDotName,Microsoft.Dafny.ResolutionContext,System.Boolean,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CreateResolver_IdentifierExpr(Microsoft.Dafny.IToken,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TopLevelDecl)
ResolveStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveLoopSpecificationComponents(System.Collections.Generic.List`1<Microsoft.Dafny.AttributedExpression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.FrameExpression>,Microsoft.Dafny.ResolutionContext)
ResolveParameterDefaultValues(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ResolutionContext)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.ExprDotName)
ResolveTypeLenient(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean)
FillInTypeArguments(Microsoft.Dafny.IToken,System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,Microsoft.Dafny.Resolver/ResolveTypeOption)
TypeConstraintsIncludeProxy(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy)
TypeConstraintsIncludeProxy_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ResolveTypeRhs(Microsoft.Dafny.TypeRhs,Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveMember(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,Microsoft.Dafny.NonProxyType&)
PartiallyResolveTypeForMemberSelection(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,System.Int32)
GetBaseTypeFromProxy(Microsoft.Dafny.TypeProxy,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_Eq(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_EqAux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetRelatedTypeProxies(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
JoinOfAllSubtypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
MeetOfAllSupertypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean)
CheckVariance(Microsoft.Dafny.Type,Microsoft.Dafny.ICallable,Microsoft.Dafny.TypeParameter/TPVariance,System.Boolean)
ConstrainToIntegerType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ResolveDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<System.Tuple`3<Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.List`1<Microsoft.Dafny.MemberDecl>&,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>&)
DesugarDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>,System.Collections.Generic.Dictionary`2<System.String,System.Tuple`3<Microsoft.Dafny.BoundVar,Microsoft.Dafny.IdentifierExpr,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean,Microsoft.Dafny.ModuleDecl&)
ResolveDatatypeConstructor(Microsoft.Dafny.NameSegment,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Tuple`2<Microsoft.Dafny.DatatypeCtor,System.Boolean>,System.String,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
ResolveNameSegment_Type(Microsoft.Dafny.NameSegment,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveDotSuffix(Microsoft.Dafny.ExprDotName,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean)
CheckForAmbiguityInShadowedImportedModule(Microsoft.Dafny.ModuleDecl,System.String,Microsoft.Dafny.IToken,System.Boolean,System.Boolean)
NameConflictsWithModuleContents(Microsoft.Dafny.ModuleDecl,System.String,System.Boolean,System.Boolean)
ResolveExprDotCall(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.Type,Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveApplySuffix(Microsoft.Dafny.ApplySuffix,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveDatatypeValue(Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.DatatypeValue,Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Type,System.Boolean)
ResolveFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,Microsoft.Dafny.ResolutionContext)
ResolveReceiver(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveSeqSelectExpr(Microsoft.Dafny.SeqSelectExpr,Microsoft.Dafny.ResolutionContext)
get_Options()
.ctor(Microsoft.Dafny.DafnyOptions)
get_Reporter()
get_TypeConstraintErrorsToBeReported()
RevealedInScope(Microsoft.Dafny.Declaration)
VisibleInScope(Microsoft.Dafny.Declaration)
FreshTempVarName(System.String,Microsoft.Dafny.ICodeContext)
Create(Microsoft.Dafny.ModuleDefinition,Thing,Thing,System.Collections.Generic.IEqualityComparer`1<Thing>,System.Collections.Generic.ISet`1<Thing>&)
Name(System.Collections.Generic.ISet`1<Thing>,System.Func`2<Thing,System.String>)
ModuleNames(Microsoft.Dafny.Resolver/IAmbiguousThing`1<Thing>,System.Func`2<Thing,System.String>)
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
Equals(Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
GetHashCode(Microsoft.Dafny.TopLevelDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.TopLevelDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()
ModuleNames()
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
Equals(Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
GetHashCode(Microsoft.Dafny.MemberDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()
ModuleNames()
.ctor(Microsoft.Dafny.Program)
AddRotateMember(Microsoft.Dafny.ValuetypeDecl,System.String,Microsoft.Dafny.Type)
ObjectInvariant()
AsValuetypeDecl(Microsoft.Dafny.Type)
CheckDupModuleNames(Microsoft.Dafny.Program)
ResolveProgram(Microsoft.Dafny.Program)
ResolveValuetypeDecls()
ResolveModuleDefinition(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Boolean)
ResolveModuleExport(Microsoft.Dafny.LiteralModuleDecl,Microsoft.Dafny.ModuleSignature)
CheckModuleExportConsistency(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver/ModuleBindings)
BindName(System.String,Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings)
TryLookup(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&)
TryLookupFilter(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&,System.Func`2<Microsoft.Dafny.ModuleDecl,System.Boolean>)
get_ModuleList()
SubBindings(System.String)
BindModuleNames(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings)
ShortenPrefix(System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>)
BindModuleName_LiteralModuleDecl(Microsoft.Dafny.LiteralModuleDecl,System.Collections.Generic.List`1<System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>>,Microsoft.Dafny.Resolver/ModuleBindings)
ResolveQualifiedModuleIdRootRefines(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootImport(Microsoft.Dafny.AliasModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootAbstract(Microsoft.Dafny.AbstractModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ProcessDependenciesDefinition(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ProcessDependencies(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ModuleNotFoundErrorMessage(System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Name>,System.String)
EquivIfPresent(System.Collections.Generic.Dictionary`2<T1,T2>,T1,T2)
MergeSignature(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleSignature)
ResolveOpenedImports(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,System.Boolean,Microsoft.Dafny.Resolver)
ResolveAlias(Microsoft.Dafny.TopLevelDecl)
ResolveOpenedImportsWorker(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDecl,System.Collections.Generic.HashSet`1<Microsoft.Dafny.ModuleSignature>,System.Boolean,Microsoft.Dafny.TopLevelDecl&)
RegisterTopLevelDecls(Microsoft.Dafny.ModuleDefinition,System.Boolean)
RegisterMembers(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDeclWithMembers,System.Collections.Generic.Dictionary`2<System.String,Microsoft.Dafny.MemberDecl>)
RegisterByMethod(Microsoft.Dafny.Function,Microsoft.Dafny.TopLevelDeclWithMembers)
MakeAbstractSignature(Microsoft.Dafny.ModuleSignature,System.String,System.Int32,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
CloneDeclaration(Microsoft.Dafny.VisibilityScope,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.ModuleDefinition,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
ResolveModuleQualifiedId(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ErrorReporter)
ResolveExport(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleQualifiedId,System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.ModuleSignature&,Microsoft.Dafny.ErrorReporter)
RevealAllInScope(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.VisibilityScope)
ResolveTopLevelDecls_Signatures(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
.cctor()
ResolveTopLevelDecls_Core(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>,System.String,System.Boolean)
FillInPostConditionsAndBodiesOfPrefixLemmas(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>)
CheckIsOkayWithoutRHS(Microsoft.Dafny.ConstantField)
ResolveClassMembers_Pass1(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckForUnnecessaryEqualitySupportDeclarations(Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CheckParameterDefaultValuesAreCompilable(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ICodeContext)
ReportCallGraphCycleError(Microsoft.Dafny.ICallable,System.String)
ReportCycleError(System.Collections.Generic.List`1<X>,System.Func`2<X,Microsoft.Dafny.IToken>,System.Func`2<X,System.String>,System.String)
MaxBV(Microsoft.Dafny.Type)
MaxBV(System.Int32)
FigureOutNativeType(Microsoft.Dafny.NewtypeDecl)
CheckOlderParameters(Microsoft.Dafny.Function)
CheckExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
CheckExpression(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
VisitOneExpr(Microsoft.Dafny.Expression)
VisitOneStmt(Microsoft.Dafny.Statement)
CheckForFuelAdjustments(Microsoft.Dafny.IToken,Microsoft.Dafny.Attributes,Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/FuelAdjustment_Context&)
Invert(Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
KNatMismatchError(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.ExtremePredicate/KType,Microsoft.Dafny.ExtremePredicate/KType)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremePredicate)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/CallingPosition&)
ExtremePredicateChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremePredicate,Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremeLemma)
VisitOneStmt(Microsoft.Dafny.Statement)
VisitOneExpr(Microsoft.Dafny.Expression)
ExtremeLemmaChecks(Microsoft.Dafny.Statement,Microsoft.Dafny.ExtremeLemma)
ExtremeLemmaChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremeLemma)
CheckTypeCharacteristics_Stmt(Microsoft.Dafny.Statement,System.Boolean)
CheckTypeCharacteristics_Expr(Microsoft.Dafny.Expression,System.Boolean)
CheckTypeCharacteristics_Type(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,System.Boolean&)
VisitOneExpr(Microsoft.Dafny.Expression,System.Boolean&)
VisitType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
CheckTypeInstantiation(Microsoft.Dafny.IToken,System.String,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Boolean)
CheckCharacteristics(Microsoft.Dafny.TypeParameter/TypeParameterCharacteristics,Microsoft.Dafny.Type,System.Boolean,System.String&,System.String&)
TypeEqualityErrorMessageHint(Microsoft.Dafny.Type)
CanCompareWith(Microsoft.Dafny.Expression)
ComputeGhostInterest(Microsoft.Dafny.Statement,System.Boolean,System.String,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICallable)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
CheckInit(System.Collections.Generic.List`1<Microsoft.Dafny.Statement>)
CheckInit(Microsoft.Dafny.Statement)
VisitExpr(Microsoft.Dafny.Expression)
VisitOneExpr(Microsoft.Dafny.Expression,System.Int32&)
LiberalRHSVisit(Microsoft.Dafny.Expression)
IsThisDotField(Microsoft.Dafny.MemberSelectExpr)
IsCollectionOperator(Microsoft.Dafny.BinaryExpr/ResolvedOpcode)
InferRequiredEqualitySupport(Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type)
ResolveParentTraitTypes(Microsoft.Dafny.TopLevelDeclWithMembers,Microsoft.Dafny.Graph`1<Microsoft.Dafny.TopLevelDeclWithMembers>)
RegisterInheritedMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberTypes(Microsoft.Dafny.TopLevelDeclWithMembers)
InheritedTraitMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckOverride_FunctionParameters(Microsoft.Dafny.Function,Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_MethodParameters(Microsoft.Dafny.Method,Microsoft.Dafny.Method,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_TypeParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_ResolvedParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.String,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
SccStratosphereCheck(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ComputeGroundingCtor(Microsoft.Dafny.IndDatatypeDecl)
CheckCanBeConstructed(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeParameter>)
DetermineEqualitySupport(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
IsRecognizedAttribute(Microsoft.Dafny.UserSuppliedAttributes,Microsoft.Dafny.IAttributeBearingDeclaration)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Microsoft.Dafny.IVariable>,Microsoft.Dafny.IVariable,System.String)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Thing>,System.String,Thing,Microsoft.Dafny.IToken,System.String)
ResolveFunctionSignature(Microsoft.Dafny.Function)
DisallowNonGhostFieldSpecifiers(Microsoft.Dafny.FrameExpression)
ResolveMethodSignature(Microsoft.Dafny.Method)
ResolveIteratorSignature(Microsoft.Dafny.IteratorDecl)
ObjectInvariant()
.ctor(Microsoft.Dafny.ResolveTypeOptionEnum)
.ctor(Microsoft.Dafny.TypeParameter/ParentType)
ResolvedArrayType(Microsoft.Dafny.IToken,System.Int32,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,System.Boolean)
FillInDefaultLoopDecreases(Microsoft.Dafny.LoopStmt,Microsoft.Dafny.Expression,System.Collections.Generic.List`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.ICallable)
VarDotMethod(Microsoft.Dafny.IToken,System.String,System.String)
makeTemp(System.String,Microsoft.Dafny.AssignOrReturnStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Expression)
EnsureSupportsErrorHandling(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,System.Boolean)
CheckLocalityUpdates(Microsoft.Dafny.Statement,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
CheckLocalityUpdatesLhs(Microsoft.Dafny.Expression,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
ToString()
FindAllMembers(Microsoft.Dafny.ClassDecl,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
GetThisType(Microsoft.Dafny.IToken,Microsoft.Dafny.TopLevelDeclWithMembers)
GetReceiverType(Microsoft.Dafny.IToken,Microsoft.Dafny.MemberDecl)
ResolveDominatingLabelInExpr(Microsoft.Dafny.IToken,System.String,System.String,Microsoft.Dafny.ResolutionContext)
VarDotFunction(Microsoft.Dafny.IToken,System.String,System.String)
LetPatIn(Microsoft.Dafny.IToken,Microsoft.Dafny.CasePattern`1<Microsoft.Dafny.BoundVar>,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
LetVarIn(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
ResolveLetOrFailExpr(Microsoft.Dafny.LetOrFailExpr,Microsoft.Dafny.ResolutionContext)
SelectAppropriateArrowTypeForFunction(Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.BuiltIns)
SelectAppropriateArrowType(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.BuiltIns)
ConstrainToIntegerType(Microsoft.Dafny.Expression,System.Boolean,System.String)
ResolveNestedMatchExpr(Microsoft.Dafny.NestedMatchExpr,Microsoft.Dafny.ResolutionContext)
ResolveCasePattern(Microsoft.Dafny.CasePattern`1<VT>,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext)
FillInDefaultValueExpressions()
FillInDefaultValueExpression(Microsoft.Dafny.DefaultValueExpression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>,Microsoft.Dafny.Expression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.IVariable,Microsoft.Dafny.Expression>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
Substitute(Microsoft.Dafny.Expression)
BuildTypeArgumentSubstitute(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
AddParentTypeParameterSubstitutions(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
GhostPrefix(System.Boolean)
GetSignatureExt(Microsoft.Dafny.ModuleSignature,System.Boolean)
GetSignature(Microsoft.Dafny.ModuleSignature)
GetImpliedTypeConstraint(Microsoft.Dafny.IVariable,Microsoft.Dafny.Type)
GetImpliedTypeConstraint(Microsoft.Dafny.Expression,Microsoft.Dafny.Type)
FreeVariables(Microsoft.Dafny.Expression)
.cctor()
get_Msg()
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
ResolveOp(Microsoft.Dafny.BinaryExpr/Opcode,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
CollectFriendlyCallsInExtremeLemmaSpecification(Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
get_IsPrefixPredicate()
get_IsExtremePredicate()
get_IsPrefixDeclaration()
.ctor(Microsoft.Dafny.IASTVisitorContext)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
get_reporter()
.ctor(Microsoft.Dafny.Resolver)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneDeclaration(Microsoft.Dafny.TopLevelDecl)
VisitField(Microsoft.Dafny.Field)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
VisitExtendedPattern(Microsoft.Dafny.ExtendedPattern,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
IsDetermined(Microsoft.Dafny.Type)
CheckTypeIsDetermined(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)
CheckTypeArgsContainNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
CheckContainsNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)